首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么BigFloat.to_s不够精确?

为什么BigFloat.to_s不够精确?
EN

Stack Overflow用户
提问于 2017-10-12 13:40:20
回答 1查看 162关注 0票数 9

我不确定这是否是个窃听器。但是我一直在玩big,我不明白为什么这些代码是这样工作的:

https://carc.in/#/r/2w96

代码语言:javascript
复制
require "big"

x = BigInt.new(1<<30) * (1<<30) * (1<<30)
puts "BigInt: #{x}"

x = BigFloat.new(1<<30) * (1<<30) * (1<<30) 
puts "BigFloat: #{x}"
puts "BigInt from BigFloat: #{x.to_big_i}"

输出

代码语言:javascript
复制
BigInt: 1237940039285380274899124224
BigFloat: 1237940039285380274900000000
BigInt from BigFloat: 1237940039285380274899124224

首先,我认为BigFloat需要更改BigFloat.default_precision以使用更大的数字。但是从这段代码看来,它只在试图输出#to_s值时才起作用。

与BigFloat设置为1024 (https://carc.in/#/r/2w98)的精度相同:

输出

代码语言:javascript
复制
BigInt: 1237940039285380274899124224
BigFloat: 1237940039285380274899124224
BigInt from BigFloat: 1237940039285380274899124224

BigFloat.to_s使用LibGMP.mpf_get_str(nil, out expptr, 10, 0, self)。GMP在哪里说:

mpf_get_str (char *str, mp_exp_t *expptr, int base, size_t n_digits, const mpf_t op) 将op转换为基基中的数字字符串。基参数可以从2到62或从-2到-36不等。最多可以生成n_digits数字。不返回尾随零。没有比op更精确地表示的数字被生成。,如果n_digits为0,则生成准确的最大数字数.

谢谢。

EN

回答 1

Stack Overflow用户

发布于 2018-09-26 18:27:24

在GMP中(它适用于所有语言,而不仅仅是水晶),整数(C mpz_t,水晶BigInt)和浮点数(C mpf_tBigFloat)具有单独的默认精度。

另外,请注意,使用显式精度比设置默认精度要好,因为默认精度可能不是重入(它依赖于configure-time开关)。另外,如果有人只读取代码的一部分,他们可能会跳过这个部分,设置默认的精度,并假设错误的部分。虽然我对水晶绑定不太了解,但我假设这样的功能是在某个地方公开的。

传递给mpf_get_str的零参数意味着从精度猜测值。我知道有效数字的数量是成比例的,并且接近precision / log2(10)。浮点数具有有限的精度。在这种情况下,使最后一个数字为零的不是mpf_get_str调用,而是内部表示没有保存这些数据。看起来您的(默认)精度太小,无法存储所有必要的数字。

总之,有两种解决办法:

  • 设置了全局默认精度。虽然这种方法可以工作,但它需要频繁地更改默认精度,或者在整个程序中使用默认精度。无论是哪种方式,默认的精确性都是拖延的一种形式,以后会有报复的。
  • 在可变的基础上设置了一个精度,这是一个比前者更好的解决方案。虽然它需要更多的代码(每个变量初始化需要多1到2行),但它将在以后偿还。例如,在空间物体跟踪系统中,物理计算必须是超精确的,但其他系统可以使用较低的精度数字来节省速度和内存。

我仍然不确定是什么使转换BigFloat --> BigInt产生缺失的数字。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46711149

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档