2017-06-22 80 views
1

我正在努力解决问题。浮点精度,并找不到解决方案。管理浮点精度

下面是一个简单的例子:

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

这样看来,在存储所述向量,R转换的数字的东西具有稍微不同的内部表示(是的,我已阅读圈1的“ R地狱“和类似的材料)。

如何强制R将输入值完全“按原样”存储,而无需修改?

就我而言,我的问题是,值以这样的方式,小的错误很迅速成长处理:

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 

所以,我需要找到一个办法让我正常化的权利。

感谢

PS-有在本网站和其他地方的许多问题,在讨论的精度明显的损失,即显示不正确的(但存储右)号的问题。在这里,例如: How to stop read.table from rounding numbers with different degrees of precision in R? 这是一个不同的问题,因为号码存储不正确(但显示正确)。

(R版本3.2.1(2015年6月18日),赢得7 64位系统)

+0

我相信你的问题是不是读表,但关于河流的数值精度https://stackoverflow.com/questions/24847918/extreme-numerical-values-in-floating-point-precision-in-r –

回答

1

浮点精度一直产生大量的混乱。关键要记住的是:当你使用双打时,没有办法按“原样”或“完全正确”的方式来存储每个实数 - 最佳可存储的是最接近的可用近似值。所以当你输入(在R或任何其他现代语言)如x = 99.93029,你会得到这个数字代表99.930289999999999

现在,如果您希望a + b为“完全100”,则表示您的准确度不准确。你可以得到的最好的结果是“小数点后100位数字”,并希望N足够大。在你的情况下,说99.9302900 + 0.0697122是100 有5个小数点的精度是正确的。当然,通过将相等乘以10^k,您将失去额外的k位精度。

所以,这里有两种解决方案:

a。为了在输出中获得更高的精度,在输入中提供更高的精度。

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

b。如果双精度不够(可能发生在复杂算法中),请使用提供额外数值精度操作的程序包。例如,包gmp

+0

要澄清,它有助于很多问题的正确设置!然而,我不明白你的例子使用bb和我的aa之间的区别?在这种情况下,你如何提供“更精确的输入”? – jfmoyen

+0

@jfmoyen'sum(aa)'是100.0000022,而sum(bb)'是100到10^-15。另一种方法是'cc < - c(99.9302878,0.0697122)'。 – tonytonov

+0

对不起,我忽略了这一点,谢谢。 – jfmoyen

0

我猜你在这里误解。 R存储正确值的情况也是如此,但是显示时选择的值相应地显示了该值。 对于EG:

# the output of below will be: 
> print(99.930289999999999,digits=20) 
[1] 99.930289999999999395 

# the output of: 
> print(1,digits=20) 
[1] 1 

而且

> print(1.1,digits=20) 
[1] 1.1000000000000000888 
+0

嗯... yeees ...我明白你的意思是最后例子与我的相似。但这意味着1存储为1,1.1存储为1.1 + 1e-16,不是吗?我想这是不可预测/不受用户控制的。我可能会得到一些“正确”的数字,并且有些“错误”。我可以理解,但那么你会如何解决这个问题(具体来说,获得'a2 /(100-a1)= 1'还是确实足够接近1)? – jfmoyen

+0

@jfmoyen,'signif'函数可以解决舍入问题(aa [2] /(100-aa [1]),digits = 1)'1在你的情况下工作吗? – parth

+0

@jfmoyen ..您在打印时不必包含数字选项。只是使用 '> print(a2 /(100-a1)= 1)''[1] 100' – ihm017

0

除了以前的答案,我认为,关于这一主题的演讲好将

[R地狱,由P.Burns

http://www.burns-stat.com/documents/books/the-r-inferno/

+1

我知道这一点,我在我原来的问题中提到它:-)可惜的是,“地狱”并不建议解决方案... – jfmoyen

+0

Ooops:D实际上没有任何(简单)解决方案。但至少它表明这是一个已知的问题:) –