Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
471 views
in Technique[技术] by (71.8m points)

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

Why does changing the sum order returns a different result?

(为什么更改总和顺序会返回不同的结果?)

23.53 + 5.88 + 17.64 = 47.05

(23.53 + 5.88 + 17.64 = 47.05)

23.53 + 17.64 + 5.88 = 47.050000000000004

(23.53 + 17.64 + 5.88 = 47.050000000000004)

Both Java and JavaScript return the same results.

(JavaJavaScript都返回相同的结果。)

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.

(我理解,由于浮点数用二进制表示的方式,一些有理数( 如1/3 - 0.333333 ...... )无法精确表示。)

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

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

  ask by Marlon Bernardes translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.

(作为我们所看到的那种事物的一个例子,让我们假设我们使用的是带有4位有效数字的十进制浮点类型,而不是二进制浮点数,其中每次加法都以“无限”精度执行,然后舍入到最近的可表示数字。)

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.

(问题是当你得到更大的数字时,更小的信息会丢失 - 在这种情况下,10001被舍入到10000。)

(This is an example of the problem that Eric Lippert noted in his answer .)

((这是Eric Lippert在答案中提到的问题的一个例子。))

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.

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...