Android: java rounding error. Can't understand why?

≡放荡痞女 提交于 2019-12-23 08:54:28

问题


Can anybody explain why on Earth these "same" expressions returns different values?

(new BigDecimal(String.valueOf(131.7d))).multiply(new BigDecimal(String.valueOf(0.95d))).doubleValue() = 125.115

(new BigDecimal(               131.7d )).multiply(new BigDecimal(               0.95d )).doubleValue() = 125.11499999999998

What BigDecimal is doing different between them?


回答1:


If you read the API documentation, you will find taht String.valueOf(dobule) uses Double.toString(double) to format the value. It's perhaps not obvious, but Double.toString(double) rounds the value, before formatting it as a string:

How many digits must be printed for the fractional part of m or a? There must be at least one digit to represent the fractional part, and beyond that as many, but only as many, more digits as are needed to uniquely distinguish the argument value from adjacent values of type double. That is, suppose that x is the exact mathematical value represented by the decimal representation produced by this method for a finite nonzero argument d. Then d must be the double value nearest to x; or if two double values are equally close to x, then d must be one of them and the least significant bit of the significand of d must be 0.

The result of this is that String.valueOf(131.7d) will return the string "131.7" even if the exact value of the argument is 131.69999999999998863131622783839702606201171875. The reason for this is that decimal fractions cannot always be represented exactly using binary fractions (as used with floats and doubles).

So, new new BigDecimal(String.valueOf(131.7)) will create a BigDecimal with the exact value 131.7. new BigDecimal(131.7) will create a BigDecimal with the exact value 131.69999999999998863131622783839702606201171875.




回答2:


If you look at the API documentation:

BigDecimal(double val)
          Translates a double into a BigDecimal which is the exact decimal representation of the double's binary floating-point value.

versus

BigDecimal(String val)
          Translates the string representation of a BigDecimal into a BigDecimal.

These are in fact not the same thing. In the double constructor it is using a floating point number (which are inherently inaccurate). In the String constructor it is taking the exact value you supplied and not doing a floating point conversion. So this does in fact mean that the constructors above are not the "same" expressions



来源:https://stackoverflow.com/questions/15685705/android-java-rounding-error-cant-understand-why

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!