这是这一类计算器的bug。
“我们人类的算术,有十个数字,从0到9,这个就是十进制。而在计算机的世界里,就只有0和1两个数字,这就是二进制。”小朱说,这个转换的过程,详细来说,就是一个数字的整数部分除以2,取余数;小数部分乘以2取整数的方法。 以14.52为例,整数部分是14:14/2=7余0 7/2=3余1 3/2=1余1 1/2=0余1 所以,14在二进制里就是1110。 小数部分是0.52: 0.52×2=1.04 整数1 0.04×2=0.08 整数0 0.08×2=0.16 整数0 0.16×2=0.32 整数0 小数部分和整数部分略有不同,小数部分很可能无穷无尽,但为了方便起见,我们只进行4次运算。于是,我们得到小数部分的结果是1000。 所以,14.52在二进制里是1110.1000 以此类推,14.49在二进制里是1110.0111 这样,14.52-14.49通过二进制运算就是1110.1000-1110.0111=0.0001 然后,我们再把它转换回十进制(二进制转换为十进制的公式为:ABC.XYZ=A×2"2+ B×2"1+C×2"0+X×2"-1+Y×2"-2+Z×2"-3,计算时,把相应的数字替换公式中的A、B、C等符号),得到的结果是0.0625。 可能有细心的读者已经发现,我们得到的结果竟然与真实的结果相差巨大,甚至比安卓的计算器还要糟糕。难道我们的算法错了?其实不然,小朱说,这与我们在小数部分进行运算的次数有关。如果我们多运算几次,精确度就会大为提高。像安卓计算机里得到的0.09999的数字,基本上我们在小数部分计算到接近30次以后,就可以实现。
■ 这不是安卓才有的bug 小朱说,之前我们已经提到,这个在当今的计算机领域几乎无法避免。但我们也可以通过一些技术手段来进行规避。比如,可以把有小数点的数字先放大,把它变成整数进行运算,之后再除以相应数字,最终就会得到精确的结果;或者事先确定要精确到的位数,然后计算到这一位之后,进行四舍五入,效果也是一样的。 在采访中,记者发现,这个问题并非安卓的计算器独有,包括百度计算器,甚至是Windows操作系统自带的计算器,也会出现这样的现象。朱宁表示,那些能得到精确结果的计算器很可能就是利用了上面的方法,进行了优化。“平时碰到了也不要大惊小怪,就当个笑话吧。”他说。
Java long 处理减法会出现减不尽的情况!这跟Java的问题!可能设计时忽略吧,属于低级bug!
类似的还有:14.52-14.49=0.029999,而不是0.03;
8.03-7.96=0.069999等等