问题
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.
回答1:
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 theBigDecimal(String)
constructor. To get that result, use the staticvalueOf(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.
回答2:
In org.json.JSONObject class comment out lines in method stringToValue(String string)
/*
* If it might be a number, try converting it. If a number cannot be
* produced, then the value will just be a string.
*/
char initial = string.charAt(0);
if ((initial >= '0' && initial <= '9') || initial == '-') {
try {
// if we want full Big Number support this block can be replaced with:
// return stringToNumber(string);
if (isDecimalNotation(string)) {
Double d = Double.valueOf(string);
if (!d.isInfinite() && !d.isNaN()) {
return d;
}
} else {
Long myLong = Long.valueOf(string);
if (string.equals(myLong.toString())) {
if (myLong.longValue() == myLong.intValue()) {
return Integer.valueOf(myLong.intValue());
}
return myLong;
}
}
} catch (Exception ignore) {
}
}
回答3:
String str = BigDecimal.valueOf(Obj.getDouble("StringName")).toPlainString();
来源:https://stackoverflow.com/questions/8710450/how-to-prevent-jsonobject-from-json-jar-converts-decimal-numbers-string-into-dou