How to prevent JSONObject from json.jar converts decimal numbers string into double

Ameya picture Ameya · Jan 3, 2012 · Viewed 9.2k times · Source

Using JSONObject to read a json response from a server. The server returns some decimal number. Normal numbers are not a problem to but the problem occurs when there is decimal number of form 0.00068. Numbers like 0.00068 are automatically stored into Double object and when an attempt is made to retrieve such number returns "computerized scientific notation" of the number , that is 6.8E4 even if the number accessed as double by getDouble(index) method or as String with getString(index) method.

Have tried this way of converting double value to string but have have eliminated this tecinique as there is some positve rounding added when Double converted to BigDecimal. This can be eliminated by rounding set while scaling to BigDecimal.ROUND_CEILING. But I don't want any scaling and want with the original values as the actual value is a small decimal number and the server guarantees the number wont exceed 6 digit after the decimal point.

BigDecimal big = new BigDecimal(new Double(0.00680));

System.out.println(big.toPlainString()); //0.006799999999999999621136392846665330580435693264007568359375

System.out.println(big.setScale(15, BigDecimal.ROUND_DOWN)); //0.006799999999999

Can there be some way to get actual string value of Double that is a number 0.00680 without scaling, or can we prevent JSONObject interpreting numbers in to their respective numeric classes.

Thanking in advance.

Answer

Jörn Horstmann picture Jörn Horstmann · Jan 3, 2012

Unrelated to the JSON library you use, you should not use the BigDecimal constructor taking a double parameter, since that uses the exact decimal representation of the double's binary floating-point value

Instead, use the static valueOf method since that uses the string value of the double and thus rounds correctly.

When a double must be used as a source for a BigDecimal, note that this constructor provides an exact conversion; it does not give the same result as converting the double to a String using the Double.toString(double) method and then using the BigDecimal(String) constructor. To get that result, use the static valueOf(double) method.

However, for very large or small numbers the parsing to a double might already have introduced rounding errors, in that case the only solution would be to use a different JSON library that supports parsing numbers as BigDecimals.