Problem with NumberFormat parameter

I am quite confused by this unusual "error" obtained when parsing a string in Double.

I have already set the properties and symbols of NumberFormat .

When passing a string with 15 digits and two decimal places (for example, str = "333333333333333,33" ) and analyzing it with Number num = NumberFormat.parse(str) , the result skips the digit.

The actual num value is 3.333333333333333E14 .

It seems to work with strings with all 1, 2, and 4, though ...

Can anyone enlighten me?

Greetings from Enrico

+3
source share
2 answers

Short answer; due to rounding error

 (double) 111111111111111.11 != (double) 111111111111111.1 

but

 (double) 333333333333333.33 == (double) 333333333333333.3 

If you need higher precision, use setParseBigDecimal and parse will return BigDecimal.


Why is this happening? This is because you are at the limit of double accuracy. 17 pieces are great because you can just imagine it. 2 simply doubles this, and two act as double vaults, each of two of all 17, so 17 are four and 17 are eights in order.

However, 17 threes takes another bit than double to represent the value, and this last bit is truncated. Similarly, 17 heels, sixes and nines also have rounding errors.

 double[] ds = { 111111111111111.11, 222222222222222.22, 333333333333333.33, 444444444444444.44, 555555555555555.55, 666666666666666.66, 777777777777777.77, 888888888888888.88, 999999999999999.99}; for (double d : ds) { System.out.println(d + " - " + new BigDecimal(d)); } 

prints the following. The double parameter is slightly rounded before printing, and BigDecimal shows the exact values ​​that double represents.

 1.1111111111111111E14 - 111111111111111.109375 2.2222222222222222E14 - 222222222222222.21875 3.333333333333333E14 - 333333333333333.3125 4.4444444444444444E14 - 444444444444444.4375 5.5555555555555556E14 - 555555555555555.5625 6.666666666666666E14 - 666666666666666.625 7.777777777777778E14 - 777777777777777.75 8.888888888888889E14 - 888888888888888.875 1.0E15 - 1000000000000000 
+6
source

In this case, the DecimalFormat.parse method returns a Double , which has limited precision .

You cannot expect it to always be able to return a number that represents the input exactly.

You can use BigDecimal.setParseBigDecimal to allow the number format to return BigDecimal from the analysis method. This Number is capable of representing your values ​​with arbitrary precision. (Thanks @Peter Lawrey for pointing this out!)

+5
source

Source: https://habr.com/ru/post/895133/


All Articles