Testing if a BigDecimal value is zero in a JSP EL Expression
Asked Answered
P

5

19

The following does not always behave as you would expect:

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

If someBigDecimal has a value of 0, but has a scale other than 0, the == operation returns false. That is, it returns true when someBigDecimal is new BigDecimal("0"), but false when someBigDecimal is new BigDecimal("0.00").

This results from the JSP 2.0, 2.1, and 2.2 specifications, which state:

For <, >, <=, >=:

If A or B is BigDecimal, coerce both A and B to BigDecimal and use the return value of A.compareTo(B).

For ==, !=:

If A or B is BigDecimal, coerce both A and B to BigDecimal and then:

  • If operator is ==, return A.equals(B)
  • If operator is !=, return !A.equals(B)

This means the == and != operators result in a call to the .equals() method, which compares not only the values, but also the scale of the BigDecimals. The other comparison operators result in a call to the .compareTo() method, which compares only the values.

Of course, the following would work:

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

But this is rather ugly, is there a better way to do this?

Pirozzo answered 6/1, 2012 at 22:54 Comment(3)
What happens if you use == 0.0?Encarnacion
@Dave Newton - I tried a test with Tomcat 6, and the literal 0.0 was coerced into a BigDecimal with a value of 0 and a scale of 0, so it made no difference. Even if it did have a scale of 1, the JSP specs only say that the value should be coerced to a BigDecimal, but say nothing about scale, so the behavior would be unpredictable.Pirozzo
@Dave Newton - I may have misspoke about the unpredictable part. According to Secion 1.18.3 of the JSP 2.2 Spec, 0.0 would be coerced to a BigDecimal using the BigDecimal constructor that takes a 'double'. This means that no matter how many zeros are after the decimal point, the resulting BigDecimal will always have a scale of 0.Pirozzo
F
13

In JSP 2.2 EL and above this expression will evaluate to true:

${someBigDecimal.unscaledValue() == 0}

This will avoid any loss of precision but assumes that someBigDecimal is always of type BigDecimal.

A custom EL function is probably the best approach for older versions of EL:

${fn:isZero(someBigDecimal)}

The core of the problem is that this Java code evaluates to false because ZERO has a scale of 0 and the new BigDecimal has a non-zero scale:

BigDecimal.ZERO.setScale(3).equals(BigDecimal.ZERO)
Friesian answered 7/1, 2012 at 11:17 Comment(1)
Thanks for your answer. We are stuck with JSP 2.1 for now. We had thought about a custom function, but I was hoping to avoid it. I now agree, though, that it is the best approach.Pirozzo
D
4
<c:if test="${someBigDecimal.compareTo(BigDecimal.ZERO) == 0}">
Dermato answered 7/1, 2012 at 10:53 Comment(1)
I think this would be the way to go if we were on the JSP 2.2 Spec. My question was limited to comparing a BigDecimal against a literal zero, but this would also work for comparing two BigDecimal values.Pirozzo
M
2

With the latest version of EL (supported by Tomcat 7 for example), you can try:

<c:if test="${someBigDecimal.doubleValue() == 0}">
Macomber answered 7/1, 2012 at 8:52 Comment(0)
P
2
<c:if test="${someBigDecimal eq 0}">
Pahang answered 4/7, 2014 at 7:25 Comment(6)
Are you saying that eq behaves differently than ==? Because it is my understanding that eq is just an alias for ==.Pirozzo
Yeah,they are different.Just like the relationship between 'equal()' and '==' in java.Pahang
Sorry, but eq is just an alias for ==; they are not different.Pirozzo
eq means the method equals(). This is the difference between equals() and ==.Pahang
Your link is for Java, but this is the JSP EL Expression Language, where eq is the same as ==. If you read the question, you will see that == results in a call to .equals(). In fact, that's the whole point of the question.Pirozzo
Sorry,I have a wrong understanding of your question.In my devolop environment,I get different results from == and eq.I don't konw the reason, maybe I get it wrong.I will check my code next Monday.Pahang
F
2

You can try signum function:

<c:if test="#{someBigDecimal.signum() == 0}">
Fairbanks answered 8/4, 2016 at 11:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.