测试 JSP EL 表达式中的大十进制值是否为零

2022-09-02 13:16:27

以下各项的行为并不总是如您所料:

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

如果某个大十进制值的值为 0,但小数位数不是 0,则 == 操作返回 false。也就是说,当 someBigDecimal 是新的 BigDecimal(“0”)时,它返回 true,但是当 someBigDecimal 是新的 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.等于(B)

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

当然,以下内容会起作用:

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

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


答案 1

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

${someBigDecimal.unscaledValue() == 0}

这将避免任何精度损失,但假设始终是类型。someBigDecimalBigDecimal

自定义 EL 函数可能是旧版本 EL 的最佳方法:

${fn:isZero(someBigDecimal)}

问题的核心是这个Java代码的计算结果为false,因为ZERO的刻度0,而新的BigDecimal的刻度为非零:

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

答案 2
<c:if test="${someBigDecimal.compareTo(BigDecimal.ZERO) == 0}">