是否可以在不诉诸任意精度数据类型的情况下消除浮点错误?

2024-04-17

我想知道在特定条件下是否可以在不诉诸任意精度数据类型的情况下消除浮点错误。

问题是常见的。语言是 Ruby,但它适用于任何语言:

f = 1829.82
=> 1829.82

f / 12.0
=> 152.485

(f / 12.0).round(2)
=> 152.48

为什么不是 152.49?因为由于浮点数的精度有限:

format("%18.14f", f)
=> "1829.81999999999994"

format("%18.14f", f / 12.0)
=> "152.48499999999999"

所以四舍五入是正确的。现在我的问题是:有没有办法得到我想要的答案,考虑到以下情况:使用 float 执行的操作(数量)有严格的限制,所需的精度限制为小数点后两位(最多 8 位)总共)和少量剩余的“错误”四舍五入的答案是可以接受的吗?

这种情况下,用户可能会输入有效的 Ruby 字符串,例如:

"foo / 12.0"

其中 foo 是执行字符串的上下文中提供的数字,而“12.0”是用户输入的内容。想象一个带有一些免费公式字段的电子表格。字符串被简单地评估为 Ruby,因此 12.0 变成了 Float。我可以使用 ruby​​_parser + ruby​​2ruby gems 构建一个解析树,将数据类型修改为 Bignum、Rational、Flt 库中的某些内容、十进制浮点表示或其他什么,但这很棘手,因为实际的字符串可能会变成有点复杂,所以我不想走这条路。如果没有其他可能的话,我会走那条路,但这个问题专门是为了看看我是否可以避免这条路。因此,12.0 的数据类型是严格的 Float,结果也是严格的 Float,我唯一能做的就是解释代码片段的最终答案,并尝试“纠正”它,如果它以“错误”的方式舍入。

用户所做的唯一计算涉及精度为两位小数的数字(总共最多 8 位)。对于“简单”,我的意思是浮点错误没有机会累积:我可以将其中两个数字相加,然后将其除以一个整数,但随后计算完成,结果被四舍五入并存储,以及任何后续计算基于该四舍五入的数字。通常只会涉及一个浮点误差,但我认为如果两个浮点误差可以累加,问题不会显着改变,尽管根据定义残余误差率可能会更大。

首先想到的可能是先四舍五入到小数点后三位,然后四舍五入到小数点后两位。但是,这是行不通的。这会导致

152.48499999999999 => 152.485 => 152.49

but also

152.4846 => 152.485 => 152.49

这不是你想要的。

接下来我想到的是向浮点数添加尽可能小的增量(正如人们指出的那样,这取决于所考虑的浮点值)if这将其推过 0.5 边界。我主要想知道这可能会导致“误报”的频率:添加最小增量的数字,即使它刚好低于 0.5 边界的事实并不是由于浮点错误,而是因为这只是计算的结果?

第二个选择是:仅always将最小的增量添加到数字中,因为无论如何 0.5 区域是唯一重要的区域。

编辑: 正如 cdiggins 所建议的那样,我只是重写了这个问题,将我的部分答案纳入评论中。我向 Ira Baxter 奖励了他积极参与讨论,尽管我还不相信他是对的:Mark Ransom 和 Emilio M Bumachar 似乎支持我的想法,即在实践中可能会进行更正大多数情况下都会产生“正确”的结果。

我仍然需要进行实验来看看结果正确的频率,我完全打算这么做,但我能花在这上面的时间有些有限,所以我还没有抽出时间来做这件事。这个实验并不简单。


听起来您想要的是固定精度的十进制数。一个好的库实现这些将比你自己组装一些东西更可靠。

对于 Ruby,请查看飞利特图书馆 http://flt.rubyforge.org/.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否可以在不诉诸任意精度数据类型的情况下消除浮点错误? 的相关文章

  • Python:计算非整数的阶乘

    我想知道是否有一种快速的 Pythonic 的方法来计算非整数的阶乘 例如 3 4 当然 内置的factorial 函数在Math模块可用 但它仅适用于积分 我不关心这里的负数 你想用math gamma x http docs pytho
  • 截断浮点数而不向上舍入

    我有一个浮点数 我想将其截断为 3 位 但我不想向上舍入 例如 转换1 0155555555555555 to 1 015 not 1 016 我将如何在 Ruby 中做到这一点 您还可以转换为 BigDecimal 并对其调用 trunc
  • 在matlab中设置图例符号的精度

    我有这个 leg2 strcat Max Degree num2str adet 1 1 ch l leg3 strcat Min Degree num2str adet 1 2 ch l leg4 strcat Max Request n
  • 为什么这个表达式会导致浮点错误?

    所以浮点运算是inexact http en wikipedia org wiki Floating point但这并不能完全解释这里发生的事情 46 pry main gt a 0 05 gt 0 05 47 pry main gt a
  • 为什么 float() 会截掉尾随零?

    该代码成功地将一个包含许多数字的大文件裁剪为几个包含数字的较小文本文件 但它产生了一个有趣的怪癖 所有数字都应精确到小数点后四位 例如 2 7400 但它们打印为 2 74 这是文件的片段 0 96 0 53 0 70 0 53 0 88
  • 是否可以用 Rust 编写 Quake 的快速 InvSqrt() 函数?

    这只是为了满足我自己的好奇心 是否有这样的实现 float InvSqrt float x float xhalf 0 5f x int i int x i 0x5f3759df i gt gt 1 x float i x x 1 5f x
  • 浮点等于的意外结果

    问题不在于为什么0 1 0 9不等于1 0 这是关于平等者的不同行为 有人可以解释为什么下面的示例的工作方式不同 float q 0 1f float w 0 9f float summ q w q w 1 0f False summ 1
  • Python 丰富比较的行为(或者,当 Decimal('100.0') < .01 时)

    所以我有一个班轮 import decimal h decimal Decimal 100 0 h gt 01 h lt 01 h gt 01 h lt 01 它所做的只是创建一个包含 100 0 的 Decimal 对象 并以各种方式将其
  • == 在 R 中,精度为 .Machine$double.eps [重复]

    这个问题在这里已经有答案了 在 R 中 我发现必须转换易于阅读的代码有点烦人 例如 if det A 1 not always working because of floating point precision to if abs de
  • Numpy 的舍入方式与 Python 不同

    The code import numpy as np a 5 92270987499999979065 print round a 8 print round np float64 a 8 gives 5 92270987 5 92270
  • python 正弦和余弦精度

    如何提高Python正弦和余弦精度 例如 我想使用以下代码 只需计算随机复向量 x 的 y cos acos x import numpy as np N 100000 x np zeros N 1j np zeros N for k in
  • 使用C标准数学库精确计算标准正态分布的CDF

    标准 C 数学库不提供计算标准正态分布 CDF 的函数 normcdf 然而 它确实提供了密切相关的函数 误差函数 erf 和互补误差函数 erfc 计算 CDF 的最快方法通常是通过误差函数 使用预定义常量 M SQRT1 2 来表示 d
  • 为什么 FLT_MIN 等于 0?

    limits h指定非浮点数学类型的限制 例如INT MIN and INT MAX 这些值是可以使用 int 表示的最大负值和最大正值 In float h 有定义FLT MIN and FLT MAX 如果您执行以下操作 NSLog f
  • MS Access 中的舍入

    VBA Access 中舍入的最佳方法是什么 我目前的方法是利用Excel方法 Excel WorksheetFunction Round 但我正在寻找一种不依赖Excel的方法 请注意 VBA Round 函数使用 Banker 舍入 将
  • 从 std::round 转换为 int 是否安全?

    我有一个问题标准 圆形 http www cplusplus com reference cmath round 带签名 double round double x 假设我有这个代码 int i std round 0 9 在这种情况下 s
  • 使用按位 OR 0 对数字进行取整

    我的一位同事偶然发现了一种使用按位或来对浮点数进行底数的方法 var a 13 6 0 a 13 我们正在谈论它并想知道一些事情 它是如何工作的 我们的理论是 使用这样的运算符将数字转换为整数 从而删除小数部分 与这样做相比 它有什么优势吗
  • 使用浮点/双除法比较可约分数

    假设我有两个分数 a b 和 c d 其中 a b c d 都是大于 0 的整数 使用以下函数检查它们的相等性是否安全 bool are equal fractions int a int b int c int d return stat
  • C++ 中的双精度型数字

    尽管内部表示有 17 位 但 IEE754 64 位 浮点应该正确表示 15 位有效数字 有没有办法强制第 16 位和第 17 位为零 Ref http msdn microsoft com en us library system dou
  • 将 numpy 舍入到最近的步骤

    我想知道如何将 numpy 中的数字舍入到上限或下限阈值 该阈值是预定义步长的函数 希望以更清晰的方式说明 如果我有数字 123 且步长等于 50 我需要将 123 舍入到最接近的 150 或 100 在本例中为 100 我得出了下面的函数
  • 浮点字节序?

    我正在为实时海上模拟器编写客户端和服务器 并且由于我必须通过套接字发送大量数据 因此我使用二进制数据来最大化可以发送的数据量 我已经了解整数字节顺序以及如何使用htonl and ntohl为了规避字节顺序问题 但我的应用程序与几乎所有模拟

随机推荐