Mau*_*ver 3 precision r tostring long-integer
我在 R 中将长数字转换为字符串时遇到问题。如何轻松地将数字转换为字符串以保持精度?下面有一个简单的例子。
a = -8664354335142704128
toString(a)
[1] "-8664354335142704128"
b = -8664354335142703762
toString(b)
[1] "-8664354335142704128"
a == b
[1] TRUE
Run Code Online (Sandbox Code Playgroud)
我期望toString(a)== toString(b),但我得到了不同的值。我想toString()在转换为字符串之前将数字转换为浮点数或类似的东西。
感谢您的帮助。
编辑:
> -8664354335142704128 == -8664354335142703762
[1] TRUE
> along = bit64::as.integer64(-8664354335142704128)
> blong = bit64::as.integer64(-8664354335142703762)
> along == blong
[1] TRUE
> blong
integer64
[1] -8664354335142704128
Run Code Online (Sandbox Code Playgroud)
我也试过:
> as.character(blong)
[1] "-8664354335142704128"
> sprintf("%f", -8664354335142703762)
[1] "-8664354335142704128.000000"
> sprintf("%f", blong)
[1] "-0.000000"
Run Code Online (Sandbox Code Playgroud)
编辑2:
我的问题首先是,如果我可以将长数转换为字符串而不会丢失。然后我意识到,在 R 中是不可能获得传递给函数的长数的真实值,因为 R 会自动读取带有损失的值。
例如,我有这样的功能:
> my_function <- function(long_number){
+ string_number <- toString(long_number)
+ print(string_number)
+ }
Run Code Online (Sandbox Code Playgroud)
如果有人使用它并传递了一个很长的数字,我将无法获得确切传递了哪个数字的信息。
> my_function(-8664354335142703762)
[1] "-8664354335142704128"
Run Code Online (Sandbox Code Playgroud)
例如,如果我从文件中读取一些数字,这很容易。但这不是我的情况。我只需要使用一些用户通过的东西。
我不是 R 专家,所以我很好奇为什么它在另一种语言中有效而在 R 中无效。例如在 Python 中:
>>> def my_function(long_number):
... string_number = str(long_number)
... print(string_number)
...
>>> my_function(-8664354335142703762)
-8664354335142703762
Run Code Online (Sandbox Code Playgroud)
现在我知道了,问题在于 R 如何读取和存储数字。每种语言都可以做不同的事情。我必须改变如何将数字传递给 R 函数的方式,它解决了我的问题。
所以我的问题的正确答案是:
““我想 toString() 将数字转换为浮点数”,不,你自己做的(即使是无意的)。- 不,R 自己做的,这就是 R 读取数字的方式。
所以我将 r2evans 的答案标记为最佳答案,因为该用户帮助我找到了正确的解决方案。谢谢!
最重要的是,在转换为 64 位整数之前,您必须(在这种情况下)将大数字作为字符串读取:
bit64::as.integer64("-8664354335142704128") == bit64::as.integer64("-8664354335142703762")
# [1] FALSE
Run Code Online (Sandbox Code Playgroud)
关于您尝试过的一些要点:
“我想 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"
Run Code Online (Sandbox Code Playgroud)更恰当地说,当您将其作为数字输入然后尝试对其进行转换时,R 首先处理括号的内部。也就是说,与
bit64::as.integer64(-8664354335142704128)
Run Code Online (Sandbox Code Playgroud)
R 首先必须解析和“理解”括号内的所有内容,然后才能将其传递给函数。(这通常是编译器/语言解析的事情,而不仅仅是 R 的事情。)在这种情况下,它看到它似乎是一个(大)负浮点数,因此它创建了一个类numeric(浮点数)。只有然后它发送这个numeric的功能,但由这点精度已经丢失。因此,否则不合逻辑
bit64::as.integer64(-8664354335142704128) == bit64::as.integer64(-8664354335142703762)
# [1] TRUE
Run Code Online (Sandbox Code Playgroud)
在这种情况下,该数字的 64 位版本正好符合您的预期。
bit64::as.integer64(-8664254335142704128) # ends in 4128
# integer64
# [1] -8664254335142704128 # ends in 4128, yay! (coincidence?)
Run Code Online (Sandbox Code Playgroud)
如果减去 1,则结果相同integer64:
bit64::as.integer64(-8664354335142704127) # ends in 4127
# integer64
# [1] -8664354335142704128 # ends in 4128 ?
Run Code Online (Sandbox Code Playgroud)
这样持续了好一阵子,直到最后转移到下一个圆点
bit64::as.integer64(-8664254335142703617)
# integer64
# [1] -8664254335142704128
bit64::as.integer64(-8664254335142703616)
# integer64
# [1] -8664254335142703104
Run Code Online (Sandbox Code Playgroud)
差异为 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
Run Code Online (Sandbox Code Playgroud)
因此,bit64::as.integer64.character可能很有用,因为当您键入它或将其作为字符串读入时,精度不会丢失:
bit64::as.integer64("-8664354335142704128")
# integer64
# [1] -8664354335142704128
bit64::as.integer64("-8664354335142704128") == bit64::as.integer64("-8664354335142703762")
# [1] FALSE
Run Code Online (Sandbox Code Playgroud)仅供参考,您的号码已经接近 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
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
1844 次 |
| 最近记录: |