我在R中将长整数转换为字符串时遇到问题。如何轻松地将数字转换为字符串以保持精度?下面有一个简单的示例。
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答案标记为最佳答案,因为该用户帮助我找到了正确的解决方案。谢谢!
最佳答案
最底线,在转换为64位整数之前,您必须(在这种情况下)将大数字作为字符串读入:
bit64::as.integer64("-8664354335142704128") == bit64::as.integer64("-8664354335142703762")
# [1] FALSE
关于您尝试过的内容的几点:
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"
bit64::as.integer64(-8664354335142704128)
R必须首先解析并“理解”括号内的所有内容,然后才能将其传递给函数。 (这通常是编译器/语言解析的东西,而不仅仅是R东西。)在这种情况下,它看起来像是一个(大)负浮点数,因此它创建了一个
numeric
(浮点数)类。只有这样,它才会将此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?)
如果减去1,则得到相同的有效
integer64
:bit64::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
-.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
关于r - R:如何将长数字转换为字符串以节省精度,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54681480/