为什么更改总和顺序会返回不同的结果? [英] Why does changing the sum order returns a different result?

查看:151
本文介绍了为什么更改总和顺序会返回不同的结果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么更改总额会得到不同的结果?

23.53 + 5.88 + 17.64 = 47.05



23.53 + 17.64 + 5.88 = 47.050000000000004



Java JavaScript 返回相同的结果。



据我所知,由于浮点数用二进制表示,所以有一些有理数( = 1/3 - 0.333333 ...

为什么简单地改变元素的顺序会影响结果?


可能这个问题很愚蠢,但为什么简单地改变元素的顺序会影响结果?

它会改变值的点数根据他们的规模。作为我们看到的类的一个例子,让我们假装不是二进制浮点数,而是使用一个有四位有效数字的十进制浮点类型,其中每个加法都是在无限精度,然后四舍五入到最接近的可表示数字。这里有两个数字:

pre $ 1/3 + 2/3 + 2/3 =(0.3333 + 0.6667)+ 0.6667
= 1.000 + 0.6667(不需要四舍五入)
= 1.667(其中1.6667四舍五入为1.667)

2/3 + 2/3 + 1/3 =(0.6667 + 0.6667 )+ 0.3333
= 1.333 + 0.3333(其中1.3334四舍五入至1.333)
= 1.666(其中1.6663四舍五入至1.666)

我们甚至不需要使用非整数来解决这个问题:

 <$ c $ (100001 = 10000)-100000 =(10000 + 1) -  10000 
= 10000-10000(其中10001舍入为10000)
= 0

10000 - 10000 + 1 =(10000 - 10000)+ 1
= 0 + 1
= 1

这可能更清楚地表明,重要的部分是我们有有限数量的有效数字而不是有限数量的小数位。如果我们总是可以保持相同的小数位数,那么至少有加法和减法,我们会没事的(只要值不溢出)。问题是,当你得到更大的数字,更小的信息丢失 - 在这种情况下10001四舍五入到10000。 (这是 Eric Lippert在他的回答中提到的问题的一个例子。)



重要的是要注意右边第一行的值在所有情况下是相同的 - 所以尽管理解你的十进制数(23.53,5.88,17.64)是不重要的完全表示为 double 值,这只是一个问题,因为上面显示的问题。


Why does changing the sum order returns a different result?

23.53 + 5.88 + 17.64 = 47.05

23.53 + 17.64 + 5.88 = 47.050000000000004

Both Java and JavaScript return the same results.

I understand that, due to the way floating point numbers are represented in binary, some rational numbers (like 1/3 - 0.333333...) cannot be represented precisely.

Why does simply changing the order of the elements affect the result?

解决方案

Maybe this question is stupid, but why does simply changing the order of the elements affects the result?

It will change the points at which the values are rounded, based on their magnitude. As an example of the kind of thing that we're seeing, let's pretend that instead of binary floating point, we were using a decimal floating point type with 4 significant digits, where each addition is performed at "infinite" precision and then rounded to the nearest representable number. Here are two sums:

1/3 + 2/3 + 2/3 = (0.3333 + 0.6667) + 0.6667
                = 1.000 + 0.6667 (no rounding needed!)
                = 1.667 (where 1.6667 is rounded to 1.667)

2/3 + 2/3 + 1/3 = (0.6667 + 0.6667) + 0.3333
                = 1.333 + 0.3333 (where 1.3334 is rounded to 1.333)
                = 1.666 (where 1.6663 is rounded to 1.666)

We don't even need non-integers for this to be a problem:

10000 + 1 - 10000 = (10000 + 1) - 10000
                  = 10000 - 10000 (where 10001 is rounded to 10000)
                  = 0

10000 - 10000 + 1 = (10000 - 10000) + 1
                  = 0 + 1
                  = 1

This demonstrates possibly more clearly that the important part is that we have a limited number of significant digits - not a limited number of decimal places. If we could always keep the same number of decimal places, then with addition and subtraction at least, we'd be fine (so long as the values didn't overflow). The problem is that when you get to bigger numbers, smaller information is lost - the 10001 being rounded to 10000 in this case. (This is an example of the problem that Eric Lippert noted in his answer.)

It's important to note that the values on the first line of the right hand side are the same in all cases - so although it's important to understand that your decimal numbers (23.53, 5.88, 17.64) won't be represented exactly as double values, that's only a problem because of the problems shown above.

这篇关于为什么更改总和顺序会返回不同的结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆