3

-1 + 1 <> 0 の理由を理解するのを手伝ってもらえますか?

組み込み関数 consum()、関数 ct()、および Excel がすべて同じことをしているのに、3 つの異なる値を取得する理由を誰かが理解するのを手伝ってくれますか?

さて、答えは「ラウンド」の問題であると確信していますが、この問題のその部分がどこから来ているのかわかりません。つまり、これはすべて非常に簡単に思えます。

R では、シーケンス 'a' を作成してから cumsum(a) を実行すると、期待どおりに 0 の結果が得られません。関数を使用して同じ値を計算しようとすると、別の答えが得られます。最後に、Excel を使用して同じ値を計算しようとすると、3 番目の答えが得られます。

これは、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 になります (値を丸めません)。

4

2 に答える 2

0

丸めの問題だと思います。関数を使用して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 への丸めのしきい値を下回っているようです。

于 2015-05-21T19:45:19.340 に答える