【问题标题】:In R, why doesn't -1 + 1 = 0 [duplicate]在R中,为什么不-1 + 1 = 0 [重复]
【发布时间】:2015-08-03 15:57:23
【问题描述】:

有人可以帮我理解为什么 -1 + 1 0 吗?

有人可以帮我理解为什么当内置函数 consum()、我的函数 ct() 和 Excel 都在做同样的事情时,我会得到三个不同的值吗?

现在,我很确定答案是“圆形”问题,但我无法弄清楚这个问题的那部分来自哪里。我的意思是,这一切“看起来很简单。

在 R 中,当我构建序列“a”然后运行 ​​cumsum(a) 时,我没有得到预期的 0 结果。如果我尝试使用函数计算相同的值,我也会得到不同的答案。最后,如果我尝试使用 Excel 计算相同的值,我会得到第三个答案。

这是我使用 cumsum() 得到的结果:

> a<- seq(-1, 1, by=.1)
> a
 [1] -1.0 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1  0.0  0.1  0.2  0.3
[15]  0.4  0.5  0.6  0.7  0.8  0.9  1.0
> cumsum(a)
 [1] -1.000000e+00 -1.900000e+00 -2.700000e+00 -3.400000e+00 -4.000000e+00
 [6] -4.500000e+00 -4.900000e+00 -5.200000e+00 -5.400000e+00 -5.500000e+00
[11] -5.500000e+00 -5.400000e+00 -5.200000e+00 -4.900000e+00 -4.500000e+00
[16] -4.000000e+00 -3.400000e+00 -2.700000e+00 -1.900000e+00 -1.000000e+00
[21]  1.110223e-15

我写了一个快速函数来测试这个并期望得到相同的答案(或 0),但我得到了一个完全不同的答案。这是我的函数及其结果:

ct<- function(x){
        result = 0
        for(i in 1:length(x)){
           cat(i, ": Result = ", result, " + ", x[i], " = ", result + x[i], "\n")
           result = result + x[i]
        }
}

> ct(a)
1 : Result =  0  +  -1  =  -1 
2 : Result =  -1  +  -0.9  =  -1.9 
3 : Result =  -1.9  +  -0.8  =  -2.7 
4 : Result =  -2.7  +  -0.7  =  -3.4 
5 : Result =  -3.4  +  -0.6  =  -4 
6 : Result =  -4  +  -0.5  =  -4.5 
7 : Result =  -4.5  +  -0.4  =  -4.9 
8 : Result =  -4.9  +  -0.3  =  -5.2 
9 : Result =  -5.2  +  -0.2  =  -5.4 
10 : Result =  -5.4  +  -0.1  =  -5.5 
11 : Result =  -5.5  +  0  =  -5.5 
12 : Result =  -5.5  +  0.1  =  -5.4 
13 : Result =  -5.4  +  0.2  =  -5.2 
14 : Result =  -5.2  +  0.3  =  -4.9 
15 : Result =  -4.9  +  0.4  =  -4.5 
16 : Result =  -4.5  +  0.5  =  -4 
17 : Result =  -4  +  0.6  =  -3.4 
18 : Result =  -3.4  +  0.7  =  -2.7 
19 : Result =  -2.7  +  0.8  =  -1.9 
20 : Result =  -1.9  +  0.9  =  -1 
21 : Result =  -1  +  1  =  4.440892e-16

如果我将 for 循环中的最后一行更改为此,那么我会得到预期的答案 0:

result = round(result + x[I], digits = 2)

在 Excel 中,使用与我的 ct() 函数中相同的逻辑,我得到 -2.886580E-15 的最终结果(不四舍五入)。

【问题讨论】:

    标签: r seq cumsum


    【解决方案1】:

    这是使用具有无法精确表示的值的固定精度表示的本质。

    就像1/3 不能用固定的小数位数精确表示一样,0.1 也不能用固定的二进制位数精确表示。因此,就像3 x (1/3) 不可能给你一个固定小数位数的 1,添加多个 0.1 永远不会给你精确的二进制 1。

    所以,让我们看一下六精度十进制表示,以便更清楚地看到这一点(this 用于表示值,而不是表示):
    1 -> 1.000000
    1/3 -> .333333
    2/3 -> .666667
    3 -> 3.000000

    这给出了:

    1/3 + 2/3 -> 0.333333 + 0.666667 -> 1.000000 -> 1(耶)

    1/3 + 1/3 -> 0.333333 + 0.333333 -> 0.666666(不是2/3,哦,好吧)

    3 * 1/3 -> 3.00000 * 0.333333 -> .999999(不是1,哦,好吧)

    您如何处理这取决于您,但这应该是预期的行为。

    为了解决你的最后一个问题,为什么用两种不同的方式做“同一件事”会产生不同的结果,它来自中间四舍五入。如果您曾经使用计算器进行过计算,写下一些部分中间结果,您就会知道写下哪些中间结果会有所不同。

    【讨论】:

    【解决方案2】:

    我猜这只是四舍五入的问题。如果您使用seq.int 函数生成一个从-10 到10 的向量,然后执行cumsum,那么总和为0:

    > seq.int(-10,10,1)
    [1] -10  -9  -8  -7  -6  -5  -4  -3  -2  -1   0   1   2   3   4   5   6   7   8   9  10
    > cumsum(seq.int(-10,10,1))
    [1] -10 -19 -27 -34 -40 -45 -49 -52 -54 -55 -55 -54 -52 -49 -45 -40 -34 -27 -19 -10   0
    

    如果你真的想做一个介于 -1 和 1 之间的序列,那么只需将整数序列除以 10L

    cumsum(seq.int(-10,10,1)/10L)
    [1] -1.0 -1.9 -2.7 -3.4 -4.0 -4.5 -4.9 -5.2 -5.4 -5.5 -5.5 -5.4 -5.2 -4.9 -4.5 -4.0 -3.4 -2.7
    [19] -1.9 -1.0  0.0
    

    您仍将一如既往地处理一些舍入错误,但这似乎低于 R 的舍入为 0 的阈值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-01-26
      • 2017-08-03
      • 2014-11-11
      • 2022-09-26
      • 2012-03-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多