0

I can understand that in BigDecimals 2.0 is not equal to 2.00 because 2.00 actually uses more precision digits. What I struggle to understand is why 2E+1 is not considered to be equal to 20 because both numbers actually use the same amount of precision digits. IMHO they are merely a different representation of the exact same number.

I know, I can use stripTrailingZeros and compareTo instead of equals, I'm just interested in the reasoning behind this. Can someone maybe help me to understand this?

Jan Gassen
  • 3,406
  • 2
  • 26
  • 44
  • 1
    Your assumption that `2E+1` and `20` have the same precision is wrong. `2E+1` has one digit precision, whereas `20` has two digits precision. – Pieter12345 Jul 19 '21 at 15:06
  • [`compareTo` alone](https://docs.oracle.com/javase/9/docs/api/java/math/BigDecimal.html#compareTo-java.math.BigDecimal-) compares BigDecimals by numerical value, but not [`equals`](https://docs.oracle.com/javase/9/docs/api/java/math/BigDecimal.html#equals-java.lang.Object-). – Peter O. Jul 19 '21 at 15:07
  • 1
    @Pieter12345 No. 20 has 0 digits, and 2E+1 has -1 digits. – Michael Jul 19 '21 at 15:07
  • @Michael correct. But is this a pure technical point or is there actually any difference in those numbers? – Jan Gassen Jul 19 '21 at 15:09
  • @Michael You are mixing up scale and precision. Pieter was correct and you can just print the values of `new BigDecimal("20").precision()` and new `BigDecimal("2E+1").precision()` to see that it will print 2 and 1 respectively. At least on my machine. – OH GOD SPIDERS Jul 19 '21 at 15:17
  • 1
    `new BigDecimal("2E+1")` has a precision of 1, meaning that it can stand for any number n where 20 <= n < 30, which is not that same as `new BigDecimal("20")` which has a precision of 2 and can therefore only stand for a number x where 20 <= x < 21 – Thomas Kläger Jul 19 '21 at 15:27
  • Also note that `new BigDecimal("2.0E+1")` **has** a precision of 2 and therefore `new BigDecimal("20").equals(new BigDecimal("2.0E+1"))` returns true – Thomas Kläger Jul 19 '21 at 15:28
  • Thank you, I think I now now where I went wrong: 2E+1 is not “just” scientific notation for 2*10^2=20 but it actually means something different in BigDecimal, i.e. 20 <= n < 30 as @ThomasKläger pointed out. – Jan Gassen Jul 19 '21 at 16:52

1 Answers1

4

It's a matter of scale.

System.out.println(new BigDecimal("20").scale()); // 0
System.out.println(new BigDecimal("2E+1").scale()); // -1

BigDecimal considers numbers that are numerically equivalent but with different scales as not being equal.

Jeroen Steenbeeke
  • 3,884
  • 5
  • 17
  • 26
  • From the docs "For example, a scale of -3 means the unscaled value is multiplied by 1000." – Michael Jul 19 '21 at 15:07
  • Yeah, I've seen this in the equals method of BigDecimal `if (scale != xDec.scale)` but that still left my with the question _why_. – Jan Gassen Jul 19 '21 at 15:08
  • 2
    @JanGassen "*I can understand that in BigDecimals 2.0 is not equal to 2.00 because 2.00 actually uses more precision digits*" For exactly the same reason as that example you gave in the question. – Michael Jul 19 '21 at 15:09