R:如何将长数字转换为字符串以节省精度

问题描述 投票:3回答:1

我有一个问题是将一个长数字转换为R中的字符串。如何轻松地将数字转换为字符串以保持精度? A有一个简单的例子如下。

a = -8664354335142704128
toString(a)

[1] "-8664354335142704128"

b = -8664354335142703762
toString(b)

[1] "-8664354335142704128"

a == b

[1] TRUE

我期待toString(a) == toString(b),但我有不同的价值观。我想toString()在转换为字符串之前将数字转换为float或类似的东西。

谢谢您的帮助。

编辑:

> -8664354335142704128 == -8664354335142703762

[1] TRUE

> along = bit64::as.integer64(-8664354335142704128)
> blong = bit64::as.integer64(-8664354335142703762)
> along == blong

[1] TRUE

> blong

integer64
[1] -8664354335142704128

我也尝试过:

> as.character(blong)

[1] "-8664354335142704128"

> sprintf("%f", -8664354335142703762)

[1] "-8664354335142704128.000000"

> sprintf("%f", blong)

[1] "-0.000000"

编辑2:

我的问题首先是,如果我可以将一个长数字转换为字符串而不会丢失。然后我意识到,在R中是不可能得到一个传入函数的长数的实数值,因为R会自动读取带有损失的值。

例如,我有这个功能:

> my_function <- function(long_number){
+ string_number <- toString(long_number)
+ print(string_number)
+ }

如果有人使用它并通过了一个很长的号码,我无法获得信息,这个号码是完全通过的。

> my_function(-8664354335142703762)
[1] "-8664354335142704128"

例如,如果我从文件中读取一些数字,那很容易。但这不是我的情况。我只需要使用某些用户传递的内容。

我不是R专家,所以我很好奇为什么在另一种语言中它起作用而在R中没有。例如在Python中:

>>> def my_function(long_number):
...     string_number = str(long_number)
...     print(string_number)
... 
>>> my_function(-8664354335142703762)
-8664354335142703762

现在我知道,问题是R如何读取和存储数字。每种语言都可以做到不同。我必须改变如何将数字传递给R函数的方式,它解决了我的问题。

所以我的问题的正确答案是:

“”我想toString()将数字转换成浮点数“,不,你自己做了(即使是无意中)。” - 不,R自己做了,这就是R读数字的方式。

因此我将r2evans的答案标记为最佳答案,因为该用户帮助我找到了正确的解决方案。谢谢!

r precision tostring long-integer
1个回答
3
投票

在前面的底线,你必须(在这种情况下)在转换为64位整数之前将大数字作为字符串读取:

bit64::as.integer64("-8664354335142704128") == bit64::as.integer64("-8664354335142703762")
# [1] FALSE

关于你尝试过的一些观点:

  • “我想toString()将数字转换为浮动”,不,你自己做了(即使是无意中)。在R中,当创建一个数字时,5是一个浮点数,而5L是一个整数。即使您曾尝试将其创建为整数,但无论如何它都会抱怨并失去精度: class(5) # [1] "numeric" class(5L) # [1] "integer" class(-8664354335142703762) # [1] "numeric" class(-8664354335142703762L) # Warning: non-integer value 8664354335142703762L qualified with L; using numeric value # [1] "numeric"
  • 更合适的是,当你输入数字然后尝试转换它时,R首先处理括号内部。就是这样 bit64::as.integer64(-8664354335142704128) R首先必须解析并“理解”括号内的所有内容,然后才能将其传递给函数。 (这通常是编译器/语言解析的东西,而不仅仅是R的东西。)在这种情况下,它看到它看起来是一个(大)负浮点数,因此它创建了一个类numeric(float)。只有这样才会将此numeric发送给函数,但到此时精度已经丢失。因此不合逻辑 bit64::as.integer64(-8664354335142704128) == bit64::as.integer64(-8664354335142703762) # [1] TRUE 在这种情况下,它只是*发生该数字的64位版本等于您的意图。 bit64::as.integer64(-8664254335142704128) # ends in 4128 # integer64 # [1] -8664254335142704128 # ends in 4128, yay! (coincidence?) 如果你减去一个,它会产生相同的有效integer64bit64::as.integer64(-8664354335142704127) # ends in 4127 # integer64 # [1] -8664354335142704128 # ends in 4128 ? 这种情况持续了很长一段时间,直到它最终转移到下一个圆点 bit64::as.integer64(-8664254335142703617) # integer64 # [1] -8664254335142704128 bit64::as.integer64(-8664254335142703616) # integer64 # [1] -8664254335142703104 差异是1024或2 ^ 10不太可能是巧合。我还没有钓鱼,但我猜这里有关于32位陆地浮点精度的一些有意义的东西。
  • 幸运的是,bit64::as.integer64有几种S3方法,可用于将不同的格式/类转换为integer64 library(bit64) methods(as.integer64) # [1] as.integer64.character as.integer64.double as.integer64.factor # [4] as.integer64.integer as.integer64.integer64 as.integer64.logical # [7] as.integer64.NULL 因此,bit64::as.integer64.character可能很有用,因为当您键入或以字符串形式读取时,精度不会丢失: bit64::as.integer64("-8664354335142704128") # integer64 # [1] -8664354335142704128 bit64::as.integer64("-8664354335142704128") == bit64::as.integer64("-8664354335142703762") # [1] FALSE
  • 仅供参考,您的号码已经接近64位边界: -.Machine$integer.max # [1] -2147483647 -(2^31-1) # [1] -2147483647 log(8664354335142704128, 2) # [1] 62.9098 -2^63 # the approximate +/- range of 64-bit integers # [1] -9.223372e+18 -8664354335142704128 # [1] -8.664354e+18
© www.soinside.com 2019 - 2024. All rights reserved.