在 R 中控制打印输出中的十进制位数

Controlling number of decimal digits in print output in R

提问人:Mehper C. Palavuzlar 提问时间:2/18/2010 最后编辑:zx8754Mehper C. Palavuzlar 更新时间:3/24/2022 访问量:314684

问:

R 中有一个选项可以控制数字显示。例如:

options(digits=10)

应该以 10 位数字给出计算结果,直到 R 会话结束。在 R 的帮助文件中,digits 参数的定义如下:

位数:控制位数 打印数值时进行打印。 这只是一个建议。有效值 是 1...22,默认值为 7

所以,它说这只是一个建议。如果我喜欢始终显示 10 位数字,而不是多或少,该怎么办?

我的第二个问题是,如果我喜欢显示超过 22 位数字,即像 100 位数字这样更精确的计算怎么办?基本 R 是否可以使用,或者我需要额外的包/功能?

编辑:多亏了 jmoy 的建议,我尝试了,它给了sprintf("%.100f",pi)

[1] "3.1415926535897931159979634685441851615905761718750000000000000000000000000000000000000000000000000000"

它有 48 位小数。这是 R 可以处理的最大限制吗?

精确 位数 r-faq 输出格式

评论

5赞 Richie Cotton 2/18/2010
只有 pi 的前 15 位数字是准确的。与真实值比较 joyofpi.com/pi.html
1赞 Mehper C. Palavuzlar 2/18/2010
你是对的。为什么在 R 中有所不同?
4赞 Richie Cotton 2/18/2010
请参阅 R cran.r-project.org/doc/FAQ/ 上的常见问题解答...
2赞 Shane 2/18/2010
Mehper:我认为你误解了 R 中数字的计算表示。你可能想阅读 en.wikipedia.org/wiki/Floating_point
2赞 syntaxerror 1/25/2015
相比之下,Python 的作用完全相同:Try .结果是 48 个“真实”小数,其余 52 位数字用零填充。python -c "import math; print(format(math.pi, '.100f'))"pi

答:

61赞 Jyotirmoy Bhattacharya 2/18/2010 #1

如果您自己生成整个输出,则可以使用 ,例如sprintf()

> sprintf("%.10f",0.25)
[1] "0.2500000000"

指定要用 10 个小数点设置浮点数的格式(在 is 中表示浮点数,指定 10 个小数点)。%.10ff.10

我不知道有什么方法可以强制 R 的高级函数打印确切的数字数。

如果要打印 R 的常用数字,则显示 100 位数字是没有意义的,因为使用 64 位双精度可以获得的最佳精度约为 16 位十进制数字(查看 .机器$double.eps)。剩下的数字将只是垃圾。

评论

0赞 Mehper C. Palavuzlar 2/18/2010
实际上,我应用的一些特殊卡方测试需要数百个小数才能给出准确的结果。此外,pi 有数千个小数点。这就是为什么我想知道大约 100 位或更多数字的原因。
15赞 Shane 2/18/2010
pi 有无限数量的小数;这并不意味着计算机可以存储它们。
0赞 skan 3/10/2015
我想这是 Mathematica 优于 R 的场景。
2赞 Gregor Thomas 7/1/2017
@skan 你认为 Mathematica 存储了无限数量的小数吗?
2赞 skan 7/1/2017
@Gregor当然不是,但你可以随心所欲地输入数字。
62赞 Richie Cotton 2/18/2010 #2

它只是一个建议的原因是,你可以很容易地编写一个忽略选项值的打印函数。内置的打印和格式设置功能确实使用该值作为默认值。options

至于第二个问题,由于 R 使用有限精度算术,因此您的答案在小数点后 15 或 16 位以上不准确,因此通常不需要更多。gmp 和 rcdd 软件包处理多精度算术(通过 gmp 库的接口),但这主要与大整数有关,而不是双精度的小数位。

MathematicaMaple 将允许您根据自己的意愿给出任意数量的小数位。

编辑:
考虑小数位和有效数字之间的区别可能会有所帮助。如果你正在做统计检验,依赖于超过15个有效数字的差异,那么你的分析几乎可以肯定是垃圾。

另一方面,如果你只处理非常小的数字,那就不成问题了,因为 R 可以处理小到(通常是 2e-308)的数字。.Machine$double.xmin

比较这两个分析。

x1 <- rnorm(50, 1, 1e-15)
y1 <- rnorm(50, 1 + 1e-15, 1e-15)
t.test(x1, y1)  #Should throw an error

x2 <- rnorm(50, 0, 1e-15)
y2 <- rnorm(50, 1e-15, 1e-15)
t.test(x2, y2)  #ok

在第一种情况下,数字之间的差异只发生在许多有效数字之后,因此数据“几乎是恒定的”。在第二种情况下,尽管数字之间的差异大小相同,但与数字本身的大小相比,它们很大。


正如 e3bo 所提到的,您可以使用该包使用多精度浮点数。Rmpfr

mpfr("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825")

与常规(双精度)向量相比,这些向量使用速度较慢且占用更多内存,但如果您有条件较差的问题或不稳定的算法,则它们可能很有用。numeric

评论

4赞 e3bo 6/29/2011
正如这个 Rwiki 页面所展示的,Rmpfr 包允许在 R 中进行高精度浮点运算。
0赞 skan 3/10/2015
但是,任何 R 包都可以使用 Rmpfr 来提高其精度吗?或者它只能使用内部编码的函数?
2赞 PatrickT 5/26/2015
我当时在想,“如果你做的统计检验依赖于超过15个有效数字的差异,那么你的分析几乎可以肯定是垃圾。 但我想知道我能得出它是垃圾的位数是多少,我以为是5,但我很乐意纠正。
2赞 Lampard 2/28/2020 #3

另一种解决方案能够根据需要控制要打印的十进制数字数(如果您不想打印冗余零)

例如,如果你有一个向量,并且想得到它elementssum

elements <- c(-1e-05, -2e-04, -3e-03, -4e-02, -5e-01, -6e+00, -7e+01, -8e+02)
sum(elements)
## -876.5432

显然,最后一个数字被截断,理想的结果应该是 ,但如果设置为固定打印十进制选项,例如,冗余零生成为1-876.54321sprintf("%.10f", sum(elements))-876.5432100000

按照这里的教程:打印十进制数,如果能够识别出某个数字中有多少个十进制数字,就像这里一样,有5个十进制数字需要打印,那么我们可以为函数设置一个参数,如下所示:-876.54321format

decimal_length <- 5
formatC(sum(elements), format = "f", digits = decimal_length)
## -876.54321

我们可以根据每次查询进行更改,因此可以满足不同的十进制打印要求。decimal_length

1赞 Daniel D 3/24/2022 #4

如果您主要使用 s,则有一个强制使用数字的函数:.tibblenum()

下面是一个示例:

library(tidyverse)

data <- tribble(
  
~ weight, ~ weight_selfreport,
81.5,81.66969147005445,
72.6,72.59528130671505,
92.9,93.01270417422867,
79.4,79.4010889292196,
94.6,96.64246823956442,
80.2,79.4010889292196,
116.2,113.43012704174228,
95.4,95.73502722323049,
99.5,99.8185117967332
)

data <-
  data %>%
  mutate(across(where(is.numeric), ~ num(., digits = 3)))

data
#> # A tibble: 9 × 2
#>      weight weight_selfreport
#>   <num:.3!>         <num:.3!>
#> 1    81.500            81.670
#> 2    72.600            72.595
#> 3    92.900            93.013
#> 4    79.400            79.401
#> 5    94.600            96.642
#> 6    80.200            79.401
#> 7   116.200           113.430
#> 8    95.400            95.735
#> 9    99.500            99.819

因此,您甚至可以根据自己的需要决定使用不同的舍入选项。我发现它非常有用,并且是打印 dfs 的相当快速的解决方案。