现在本人在做系统维护,然后有时候客户提供的数据与系统数据不同,需要修改,但是修改之后客户说还有一个地方不对,我就纳闷了,明明全是按照客户给的数据去修改,怎么会不对呢。。于是仔细核对了一下两边的数据,发现对4个相同的数字求平均,我们系统中的分数跟Microsoft excel中的结果竟然不同?4个值分别是:89.51、88.51、89.5、89.9,我们系统求的分数是:89.36,Microsoftexcel中给出的分数竟然是35.5.
到这里突然觉得事情有意思起来了,于是我尝试其他几种方法来计算,自己手动计算、手机计算器,电脑计算器,甚至还下了几个APP来测试,结果发现结果一致都是89.36,确切来说是89.355.发现这点之后再去思考:是不是Microsoft excel中显示小数位的时候没有进位,于是自己手动输入数值:89.355,然后修改小数点后的显示位数,结果还是显示的89.36.
事情到这里开始变的有意思起来了,之前的几次测试明显可以得出一个结论:Microsoft excel中的计算公式有问题。于是问题发现了,可是却还不知道问题具体出现在什么地方,然后对这组数字分组测试。首先是四个数字相加,结果为357.42,没问题!然后用357.42除以4结果是89.355,还是没问题,但是用上excel中的 AVERAGE函数之后问题就出现了,结果是89.35。问题出在这个AVERAGE函数了,然后突发奇想说把小数位扩大到三位试试,结果让我震惊了,excel中的答案竟然是:89.355,竟然又正确了。好吧,微软你是在逗我玩呢!
带着不能这么轻易被戏耍的目的,又继续做了几组测试。首先是在excel中的单元格里面输入: =(89.51+88.51+89.5+89.9)/4。结果还是89.355。好吧,我有点受不了了, 但是又继续做了点测试。还是在excel中,这次我直接在单元格中输入: =(C59+D59+E59+F59)/4(那是那四个数字所在的单元格),然后求值,然后我笑了,结果是89.35488。问题所在地终于找出来了。对四个单元格的数值进行取值之后再求平均,结果就错乱了。
当然后想到前面的小数点显示位数之后我又做了件稍显无聊的事:把小数点显示位数加到6位。结果又把我吓一跳:89.354875.后面竟然还有猫腻。好吧,果断决定跟微软杠上了,把小数点显示位数一口气加到20位,然后我发现,我想多了。结果还是89.35487500000000000(后面多少个0不要深究,我懒得数了,随便加几个)。也就是说精度丢失的极限就在这了。然后一想,会不会是我的office版本问题?难道这是office2013的问题?又小小的试了几个版本,Microsoft officc2010,当然国产软件WPS office 也逃不出我的手掌心(请原谅我没有找更多版本去测试,找不到啊,再备注一下,其他版本测试方法与以上测试方法相同)。然后得出一个结论:国产软件就是强!
问题到这本来应该要结束了吧,可是还是满足不了自己的好奇心,为什么同样一组数据,在Microsoft 和WPS中得到的结果会不同?而且同样是Microsoft,在计算的时候用单元格求平局与用数值求平均所得出的结果还是不同。问题应该出在单元格这里了。是不是单元格的数值类型导致的问题?就着这个问题又做了几组测试。
首先是用C++测试,定义了两组数据一组是double类型的,a,b,c,d值也分别是上述四个,再是float类型。h,i,j,k同样也是这样四个值。再打印出来,结果是:89.355。再就是用java,也是同样分别定义,不过java中的结果有点不同,java中double类型的结果为: 89.35499999999999,float打印结果为89.355。不过这也不是关键,java中double类型本来就会丢失精度。再测,再就是C++中的long类型,以及将double,long double ,float几种类型混合起来相加并打印。结果还是89.355。 那么问题不是出在数值身上了。再去思考一下,excel中接收的输入值应该是字符串类型,而后再转换为浮点类型double或者float,也许可以从这里入手。
然后开始C++测试了,首先是4个char类型的变量,ch1,ch2,ch3,ch4.分别赋值,再分别转换为double、float、long double再混合, 结果还是清一色的89.355。同样java中也进行了这部分测试(java中没有long double就没测了)。再利用java中的JTable从中获值,好吧我都失败了,而且,这件事情也已经走出我的能力范围之外了。写出来给大神参考一下,希望到时候发现问题之后能告知我一下,满足我的好奇心。
到这里突然觉得事情有意思起来了,于是我尝试其他几种方法来计算,自己手动计算、手机计算器,电脑计算器,甚至还下了几个APP来测试,结果发现结果一致都是89.36,确切来说是89.355.发现这点之后再去思考:是不是Microsoft excel中显示小数位的时候没有进位,于是自己手动输入数值:89.355,然后修改小数点后的显示位数,结果还是显示的89.36.
事情到这里开始变的有意思起来了,之前的几次测试明显可以得出一个结论:Microsoft excel中的计算公式有问题。于是问题发现了,可是却还不知道问题具体出现在什么地方,然后对这组数字分组测试。首先是四个数字相加,结果为357.42,没问题!然后用357.42除以4结果是89.355,还是没问题,但是用上excel中的 AVERAGE函数之后问题就出现了,结果是89.35。问题出在这个AVERAGE函数了,然后突发奇想说把小数位扩大到三位试试,结果让我震惊了,excel中的答案竟然是:89.355,竟然又正确了。好吧,微软你是在逗我玩呢!
带着不能这么轻易被戏耍的目的,又继续做了几组测试。首先是在excel中的单元格里面输入: =(89.51+88.51+89.5+89.9)/4。结果还是89.355。好吧,我有点受不了了, 但是又继续做了点测试。还是在excel中,这次我直接在单元格中输入: =(C59+D59+E59+F59)/4(那是那四个数字所在的单元格),然后求值,然后我笑了,结果是89.35488。问题所在地终于找出来了。对四个单元格的数值进行取值之后再求平均,结果就错乱了。
当然后想到前面的小数点显示位数之后我又做了件稍显无聊的事:把小数点显示位数加到6位。结果又把我吓一跳:89.354875.后面竟然还有猫腻。好吧,果断决定跟微软杠上了,把小数点显示位数一口气加到20位,然后我发现,我想多了。结果还是89.35487500000000000(后面多少个0不要深究,我懒得数了,随便加几个)。也就是说精度丢失的极限就在这了。然后一想,会不会是我的office版本问题?难道这是office2013的问题?又小小的试了几个版本,Microsoft officc2010,当然国产软件WPS office 也逃不出我的手掌心(请原谅我没有找更多版本去测试,找不到啊,再备注一下,其他版本测试方法与以上测试方法相同)。然后得出一个结论:国产软件就是强!
问题到这本来应该要结束了吧,可是还是满足不了自己的好奇心,为什么同样一组数据,在Microsoft 和WPS中得到的结果会不同?而且同样是Microsoft,在计算的时候用单元格求平局与用数值求平均所得出的结果还是不同。问题应该出在单元格这里了。是不是单元格的数值类型导致的问题?就着这个问题又做了几组测试。
首先是用C++测试,定义了两组数据一组是double类型的,a,b,c,d值也分别是上述四个,再是float类型。h,i,j,k同样也是这样四个值。再打印出来,结果是:89.355。再就是用java,也是同样分别定义,不过java中的结果有点不同,java中double类型的结果为: 89.35499999999999,float打印结果为89.355。不过这也不是关键,java中double类型本来就会丢失精度。再测,再就是C++中的long类型,以及将double,long double ,float几种类型混合起来相加并打印。结果还是89.355。 那么问题不是出在数值身上了。再去思考一下,excel中接收的输入值应该是字符串类型,而后再转换为浮点类型double或者float,也许可以从这里入手。
然后开始C++测试了,首先是4个char类型的变量,ch1,ch2,ch3,ch4.分别赋值,再分别转换为double、float、long double再混合, 结果还是清一色的89.355。同样java中也进行了这部分测试(java中没有long double就没测了)。再利用java中的JTable从中获值,好吧我都失败了,而且,这件事情也已经走出我的能力范围之外了。写出来给大神参考一下,希望到时候发现问题之后能告知我一下,满足我的好奇心。