计算以后精度改变怎么办?

来源:百度知道 编辑:UC知道 时间:2024/06/18 18:45:57
在JAVA和JAVASCRIPT中计算2.3+9.3或则2.3*3的时候都会出现精度改变,前面一个显示11.60000001
请问这个问题怎么解决。
还有一个问题,就是照你这个说法,只要小数末尾不为5的他无论怎么乘2都不可能是整数,那理论上只要小数末尾不为5的小数运算都有可能出现这种情况,那么到底要保留几位呢?

这里已经说了,是否能精确表示可以用乘2取整法,最大位为1可以认为不能精确表示,如果你小数位数比较多也可能在float的长度无法精确表示。,至于表示几位完全取决于你的业务需求。
这个问题头脑一定要以二进制为中心,这样那些奇怪的舍入方式就很好理解了。
如果你数据本来就用浮点表示不精确是不可避免的,所以你可以一开始就用字符串表示,然后构造成BigDecimal进行计算。

所谓的精确本身就是不精确的,因为十进制小数到二进制有可能丢失精度,这是不可避免的。但是这点精度的损失不影响实际使用,如果你真要绝对精确就用字符串表示数据。

十进制小数化成二进制小数是用乘2区取整法。
如0.3二进制小数原码计算为0.3*2=0.6整数0,剩下0.6
0.6*2=1.2整数1,剩下0.2
0.2*2=0.4整数0,剩下0.4
0.4*2=0.8整数0,剩下0.8
0.8*2=1.6整数1,剩下0.6
这时已经构成一个循环,因此0.3不可能被精确表示。也就是说只有剩下0的时候这个十进制小数才能精确用二进制表示。
JAVA的FLOAT类型不会检测它是不是精确的,当它toString的时候它会把末尾的0截断,一个不能被精确表示的float末尾一定是1,所以就显示了最长位数。

解决的办法有两个,一个是使用近似函数把它舍入到一个能被精确表示的二进制,如java.text.DecimalFormat,它只有一种舍入模式
一个是使用有精度的引用类,如BigDecimal,它的成员函数setScale有等多种舍入模式,其中ROUND_HALF_EVEN模式效果等效于四舍五入