【问题标题】:Testing if a BigDecimal value is zero in a JSP EL Expression测试 JSP EL 表达式中的 BigDecimal 值是否为零
【发布时间】:2012-02-04 15:18:58
【问题描述】:

以下行为并不总是如您所愿:

<c:if test="${someBigDecimal == 0}">

如果 someBigDecimal 的值为 0,但比例尺不是 0,则 == 操作返回 false。即 someBigDecimal 为 new BigDecimal("0") 时返回 true,而 someBigDecimal 为 new BigDecimal("0.00") 时返回 false。

这源于 JSP 2.0、2.1 和 2.2 规范,其中规定:

对于 、=:

如果 A 或 B 是 BigDecimal,则将 A 和 B 都强制为 BigDecimal 并且 使用 A.compareTo(B) 的返回值。

对于 ==, !=:

如果 A 或 B 是 BigDecimal,则强制 A 和 B 都为 BigDecimal,然后:

  • 如果运算符为 ==,则返回 A.equals(B)
  • 如果运算符是 !=,则返回 !A.equals(B)

这意味着==!= 运算符会调用.equals() 方法,该方法不仅比较值,还比较BigDecimals 的小数位数。其他比较运算符导致调用 .compareTo() 方法,该方法仅比较值。

当然,以下是可行的:

<c:if test="${not ((someBigDecimal < 0) or (someBigDecimal > 0))}">

但这很丑陋,有没有更好的方法来做到这一点?

【问题讨论】:

  • 如果你使用== 0.0会发生什么?
  • @Dave Newton - 我尝试使用 Tomcat 6 进行测试,文字 0.0 被强制转换为值为 0 且比例为 0 的 BigDecimal,因此没有区别。即使它确实有 1 的比例,JSP 规范也只说该值应该被强制为 BigDecimal,但没有提到比例,所以行为将是不可预测的。
  • @Dave Newton - 我可能误会了不可预测的部分。根据 JSP 2.2 规范的第 1.18.3 节,0.0 将被强制为 BigDecimal 使用采用“双”的 BigDecimal 构造函数。这意味着无论小数点后有多少个零,生成的 BigDecimal 的比例始终为 0。

标签: java jsp el bigdecimal


【解决方案1】:

用最新版本的EL(比如Tomcat 7支持),你可以试试:

<c:if test="${someBigDecimal.doubleValue() == 0}">

【讨论】:

    【解决方案2】:
    <c:if test="${someBigDecimal.compareTo(BigDecimal.ZERO) == 0}">
    

    【讨论】:

    • 我认为如果我们使用 JSP 2.2 规范,这将是可行的方法。我的问题仅限于将 BigDecimal 与文字零进行比较,但这也适用于比较两个 BigDecimal 值。
    【解决方案3】:

    在 JSP 2.2 EL 及更高版本中,此表达式的计算结果为 true

    ${someBigDecimal.unscaledValue() == 0}
    

    这将避免任何精度损失,但假定 someBigDecimal 始终是 BigDecimal 类型。

    custom EL function 可能是旧版本 EL 的最佳方法:

    ${fn:isZero(someBigDecimal)}
    

    问题的核心在于,这个 Java 代码的计算结果为 false,因为 ZEROscale0,而新的 BigDecimal 具有非零比例:

    BigDecimal.ZERO.setScale(3).equals(BigDecimal.ZERO)
    

    【讨论】:

    • 感谢您的回答。我们现在被 JSP 2.1 困住了。我们曾考虑过自定义函数,但我希望避免它。不过,我现在同意这是最好的方法。
    【解决方案4】:
    <c:if test="${someBigDecimal eq 0}">
    

    【讨论】:

    • 您是说eq 的行为与== 不同吗?因为据我了解eq 只是== 的别名。
    • 是的,它们是不同的。就像java中'equal()'和'=='之间的关系。
    • 对不起,eq 只是== 的别名; they are not different.
    • eq 表示方法equals()Thisequals()== 之间的区别。
    • 您的链接适用于 Java,但这是 JSP EL 表达式语言,其中 eq== 相同。如果您阅读该问题,您将看到== 导致调用.equals()。事实上,这就是问题的全部意义所在。
    【解决方案5】:

    你可以试试signum函数:

    <c:if test="#{someBigDecimal.signum() == 0}">
    

    【讨论】:

      猜你喜欢
      • 2023-03-14
      • 1970-01-01
      • 1970-01-01
      • 2011-09-09
      • 1970-01-01
      • 2013-12-28
      • 1970-01-01
      • 2014-01-23
      • 2011-06-30
      相关资源
      最近更新 更多