floating-point - 是否可以在不求助于任意精度数据类型的情况下消除浮点错误?

标签 floating-point rounding precision

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

问题是通常的。语言是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"

因此,四舍五入是正确的。现在我的问题是:在以下情况下,是否有办法获得我想要的答案:使用浮点数执行的操作数有严格的限制,所需的精度限制为两位小数(最大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位数字)。 “简单”是指浮点误差没有积累的机会:我可以将这些数字中的两个相加,然后用一个整数除以一个整数,然后完成计算,将结果四舍五入并存储,然后进行任何后续计算基于该四舍五入的数字。通常只涉及一个浮点错误,但是我认为,如果两个可以累加,该问题不会显着改变,尽管从定义上讲,残余错误率可能更大。

首先想到的是先四舍五入到十进制数字,然后四舍五入到2。但是,这不起作用。那会导致
152.48499999999999 => 152.485 => 152.49

但是也
152.4846 => 152.485 => 152.49

这不是你想要的。

接下来我想到的是,如果将浮点微调到.5边界,则将最小的增量(正如人们指出的那样,取决于所考虑的浮点值)。我主要想知道这多久会导致“假阳性”:一个添加了最小增量的数字,即使该数字恰好位于.5边界以下不是由于浮点错误引起的,而是因为这仅仅是计算的结果?

第二种选择是:始终将最小的增量添加到数字上,因为无论如何,.5区域是唯一重要的区域。

编辑:
我只是改写了这个问题,以便根据评论家的建议将我的部分答案纳入注释中。我授予Ira Baxter积极参与讨论的奖金,尽管我尚未确信他是对的:Mark Ransom和Emilio M Bumachar似乎支持我的想法,即在实践中可能进行更正在大多数情况下,会产生“正确”的结果。

我仍然必须进行实验,以查看结果正确的频率,并且我完全打算这样做,但是我可以花时间的时间有限,所以我还没有解决这个问题。实验并非无关紧要。

最佳答案

听起来您想要的是固定精度的十进制数字。一个好的实现这些功能的库将比自己一起骇入某些东西更加可靠。

对于Ruby,请查看Flt library

关于floating-point - 是否可以在不求助于任意精度数据类型的情况下消除浮点错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6359116/

相关文章:

javascript - 舍入javascript变量

python - 如何防止 csv.DictWriter() 或 writerow() 舍入我的 float ?

python-3.x - 使用 openpyxl 从 excel 中读取列时精度丢失

javascript - 如何使用 Javascript 来平均划分一个圆,使其正确到 1,000,000,000% 缩放?

java - 数学线只在一个循环中运行一次

python - 如何最好地处理这个 Python 数值错误?

c# - 我什么时候会遇到C#中Double类型的问题(比特币的小数点后8位)?

ruby - 两种舍入方法给出不同的结果

delphi - 如何避免 ftFmtBcd 失去精度?

.net - 如何在 Windows 注册表中存储 double 型(64 位浮点型)或浮点型?