我有时必须处理非常低的p值并以表格格式呈现它们。 R返回的值可以具有长有效数字(即小数点后的数字)。 现在因为p值总是如此之低,我倾向于在将它们写入.xls或.tsv文件之前将它们缩短。(只是为了使表看起来很漂亮!!)
我正在使用R version 3.0.0 (2013-04-03)
一些背景和示例:
R中的 9.881313e-208
将在我的表格中9.88e-208
我可以使用R中的round
函数来执行此操作。
round(9.881313e-208, 210)
[1] 9.88e-208
然而,e
的功效值在每种情况下都会有所不同,因为有很多这样的情况,我使用以下公式: -
x = 9.881313e-208
round(x,abs(floor(log10(x)-2))) ## I came to this following trial and error
[1] 9.88e-208
我已经根据经验测试了这个公式,它适用于不同的情况,如: -
a <- c(1.345678e-150,8.543678e-250,5.555555e-303, 0.01123, 4.523456e-290)
round(a,abs(floor(log10(a)-2)))
[1] 1.35e-150 8.54e-250 5.56e-303 1.12e-02 4.52e-290
现在问题开始时e
的力量超过数字306(即使307很好,但在308之后开始变得奇怪)
## Example 1:
b <- c(1.345678e-306,1.345678e-307,1.345678e-308, 1.345678e-309, 1.345678e-310)
round(b,abs(floor(log10(b)-2)))
[1] 1.35e-306 1.30e-307 1.00e-308 0.00e+00 0.00e+00
## Example 2:
b <- c(3.345678e-306,3.345678e-307,3.345678e-308, 3.345678e-309, 3.345678e-310)
round(b,abs(floor(log10(b)-2)))
[1] 3.35e-306 3.30e-307 3.00e-308 0.00e+00 0.00e+00
## Example 3:
b <- c(7.345678e-306,7.345678e-307,7.345678e-308, 7.345678e-309, 7.345678e-310)
round(b,abs(floor(log10(b)-2)))
[1] 7.35e-306 7.30e-307 7.00e-308 1.00e-308 0.00e+00
另外,我直接检查了这些:
round(7.356789e-306,308)
[1] 7.36e-306
round(7.356789e-307,309)
[1] 7.4e-307
round(7.356789e-308,310)
[1] 7e-308
round(7.356789e-309,311)
[1] 1e-308
round(7.356789e-310,312)
[1] 0
round(7.356789e-311,313)
[1] 0
我在这里遗漏了一些微不足道的事情,或round
函数是否超出e-308
的分辨率限制。我知道这些值非常低,几乎等于零,但我仍然希望有确切的值。我在使用Python看到了这个问题的一些答案,(参见How right way to round a very small negative number?)但是我有什么建议可以在R中克服这个问题吗?
非常感谢
干杯
阿斯温
答案 0 :(得分:4)
这个答案是基于R&#39的浮点数由IEEE 754 64位二进制数表示的假设。这与报告的结果一致,并且本身很可能。
对绝对幅度低于约2e-308的数字进行大量算术是非常有问题的。低于该点,精度会随着幅度下降。最小的可表示数字,约4.9E-324,其表示中有一个重要位。它的一对相邻数字是0和大约1.0E-323。 任何舍入错误都会将其减少为零或加倍。它不会遇到仅影响其十进制表示中的低有效位数的细微舍入误差。同样,round
也无法轻微改变。它可以保持不变,加倍,返回0,或者做出更大的改变。
有关正在发生的事情的更多说明,请参阅Denormal number。
解决方案是,如果可能的话,避免对这么小的数字进行算术运算。正如评论中已经指出的那样,一种好的方法是使用对数。如果你需要处理非常大和非常小的数字,这是唯一的方法。
如果这是不可能的,并且您的数字都很小,请考虑使用2的中等大小进行缩放。范围内两个的幂是完全可表示的,并且乘以它们仅改变指数,没有舍入误差。在舍入之前,您可以通过常量缩放要存储在文本文件中的所有数字。
答案 1 :(得分:0)
要解决此问题,您可以使用Rmpfr
库。
示例:
library(Rmpfr)
x <- mpfr(7.356789e-311, 80)
round(x, 313)
1 'mpfr' number of precision 1040 bits
[1]7.36000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008e-311