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?

John S
  • 21,212
  • 8
  • 46
  • 56
  • What happens if you use `== 0.0`? – Dave Newton Jan 07 '12 at 02:37
  • @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. – John S Jan 08 '12 at 02:35
  • @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. – John S Jan 08 '12 at 03:17

5 Answers5

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)
McDowell
  • 107,573
  • 31
  • 204
  • 267
  • 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. – John S Jan 08 '12 at 03:35
4
<c:if test="${someBigDecimal.compareTo(BigDecimal.ZERO) == 0}">
Assen Kolov
  • 4,143
  • 2
  • 22
  • 32
  • 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. – John S Jan 08 '12 at 19:03
2
<c:if test="${someBigDecimal eq 0}">
peakmuma
  • 1,544
  • 1
  • 9
  • 9
  • 1
    Are you saying that `eq` behaves differently than `==`? Because it is my understanding that `eq` is just an alias for `==`. – John S Jul 06 '14 at 01:40
  • Yeah,they are different.Just like the relationship between 'equal()' and '==' in java. – peakmuma Jul 26 '14 at 02:00
  • 2
    Sorry, but `eq` is just an alias for `==`; [they are not different](http://stackoverflow.com/questions/2087721/difference-between-eq-and-in-jsp). – John S Jul 28 '14 at 14:44
  • `eq` means the method `equals()`. [This](http://stackoverflow.com/questions/513832/how-do-i-compare-strings-in-java) is the difference between `equals()` and `==`. – peakmuma Aug 02 '14 at 04:02
  • 1
    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. – John S Aug 02 '14 at 04:17
  • 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. – peakmuma Aug 02 '14 at 05:13
2

You can try signum function:

<c:if test="#{someBigDecimal.signum() == 0}">
Saljack
  • 2,072
  • 21
  • 24
2

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

<c:if test="${someBigDecimal.doubleValue() == 0}">
Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140