Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In R, why doesn't -1 + 1 = 0 [duplicate]

Tags:

r

seq

cumsum

Can someone please help me understand why -1 + 1 <> 0 ?

Can someone please help me understand why I get three different values between the built-in function consum(), my function ct(), and Excel when they are all doing the same thing?

Now, I'm pretty sure the answer is a 'round' issue, but I can't figure out where that part of this issue is coming from. I mean, this all 'seems pretty straight forward.

In R, when I build the sequence 'a' and then run cumsum(a) I don't get the result of 0 like I expect to get. I also get a different answer if I try to calculate the same value using a function. Finally, I get a third answer if I try to calculate the same value using Excel.

This is what I get using 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

I wrote a quick function to test this and expected to get the same answer (or 0), but I get a totally different answer. Here is my function with its results:

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

If I change the last line in the for loop to this, then I get the expected answer of 0:

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

In Excel, using the same logic as in my ct() function, I get a final result of -2.886580E-15 (without rounding the values).

like image 959
dave Avatar asked Jan 31 '26 23:01

dave


1 Answers

This is the nature of using a fixed-precision representation with values that it cannot represent exactly.

Just like 1/3 can't be represented exactly with a fixed number of decimal places, 0.1 can't be represented exactly with a fixed number of binary places. So just like 3 x (1/3) can't possibly give you 1 with a fixed number of decimal places, adding multiples of 0.1 will never give you exactly 1 in fixed-precision binary.

So, let's look at six-precision decimal representation just to see this more clearly (this is used to indicate values, as opposed to representations):
1 -> 1.000000
1/3 -> .333333
2/3 -> .666667
3 -> 3.000000

This gives:

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

1/3 + 1/3 -> 0.333333 + 0.333333 -> 0.666666 (not 2/3, oh well)

3 * 1/3 -> 3.00000 * 0.333333 -> .999999 (not 1, oh well)

How you handle this is up to you, but this should be expected behavior.

To address your last question, why doing the "same thing" two different ways can produce different results, it comes from intermediate rounding. If you've ever done a computation with a calculator, writing down some of the partial intermediate results, you know it can make a difference which intermediate results you write down.

like image 117
David Schwartz Avatar answered Feb 03 '26 12:02

David Schwartz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!