Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Managing floating point accuracy

Tags:

r

precision

I'm struggling with issues re. floating point accuracy, and could not find a solution.

Here is a short example:

aa<-c(99.93029, 0.0697122)
aa
[1] 99.9302900  0.0697122
aa[1]
99.93029
print(aa[1],digits=20)
99.930289999999999

It would appear that, upon storing the vector, R converted the numbers to something with a slightly different internal representation (yes, I have read circle 1 of the "R inferno" and similar material).

How can I force R to store the input values exactly "as is", with no modification?

In my case, my problem is that the values are processed in such a way that the small errors very quickly grow:

aa[2]/(100-aa[1])*100
[1] 100.0032 ## Should be 100, of course !
print(aa[2]/(100-aa[1])*100,digits=20)
[1] 100.00315593171625

So I need to find a way to get my normalization right.

Thanks

PS- There are many questions on this site and elsewhere, discussing the issue of apparent loss of precision, i.e. numbers displayed incorrectly (but stored right). Here, for instance: How to stop read.table from rounding numbers with different degrees of precision in R? This is a distinct issue, as the number is stored incorrectly (but displayed right).

(R version 3.2.1 (2015-06-18), win 7 x64)

like image 376
jfmoyen Avatar asked May 31 '26 07:05

jfmoyen


1 Answers

Floating point precision has always generated lots of confusion. The crucial idea to remember is: when you work with doubles, there is no way to store each real number "as is", or "exactly right" -- the best you can store is the closest available approximation. So when you type (in R or any other modern language) something like x = 99.93029, you'll get this number represented by 99.930289999999999.

Now when you expect a + b to be "exactly 100", you're being inaccurate in terms. The best you can get is "100 up to N digits after the decimal point" and hope that N is big enough. In your case it would be correct to say 99.9302900 + 0.0697122 is 100 with 5 decimal points of accuracy. Naturally, by multiplying that equality by 10^k you'll lose additional k digits of accuracy.

So, there are two solutions here:

a. To get more precision in the output, provide more precision in the input.

bb <- c(99.93029, 0.06971) 
print(bb[2]/(100-bb[1])*100, digits = 20)
[1] 99.999999999999119

b. If double precision not enough (can happen in complex algorithms), use packages that provide extra numeric precision operations. For instance, package gmp.

like image 195
tonytonov Avatar answered Jun 02 '26 20:06

tonytonov



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!