是否可以在不求助于任意精度数据类型的情况下消除浮点错误?
|
我想知道在特定条件下是否可以在不诉诸于任意精度数据类型的情况下消除浮点错误。
问题是通常的。语言是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 + ruby2ruby gem来构建一个解析树,将数据类型修改为Bignum,Rational,Flt库中的某些内容,十进制浮点表示形式或具有什么功能,但这很棘手,因为实际的字符串可能会变成稍微复杂一点,所以我不喜欢这样。如果没有其他可能,我将按照这种方式进行操作,但是此问题专门用于查看我是否可以避免这种情况。因此,12.0的数据类型严格为Float,结果严格为Float,我唯一能做的就是解释代码段的最终答案,并尝试对其进行“校正”,如果它四舍五入为“错误”, ' 办法。
用户所做的唯一计算涉及的数字精度为两位十进制数字(总共最多8位数字)。使用\'simple \',我的意思是浮点错误没有机会累积:我可以将这些数字中的两个相加,然后用一个整数除以一个整数,但是然后完成计算,将结果四舍五入并存储,并且随后的计算基于该四舍五入的数字。通常只涉及一个浮点错误,但我认为,如果两个可以累加,问题不会显着改变,尽管从定义上讲,残余错误率可能更大。
首先想到的是先四舍五入到十进制数字,然后四舍五入到2。但是,这不起作用。那会导致
152.48499999999999 => 152.485 => 152.49
但是也
152.4846 => 152.485 => 152.49
这不是你想要的。
我接下来想到的是,如果将浮点微调到.5边界,则将最小的增量(正如人们指出的那样,取决于所考虑的浮点值)。我主要是想知道这会多久产生一次“误报”:一个数字,其增量最小,即使该数字恰好位于.5边界以下不是由于浮点引起的错误,但是因为这仅仅是计算的结果?
第二种选择是:始终将最小的增量添加到数字上,因为无论如何,.5区域是唯一重要的区域。
编辑:
我只是改写了这个问题,以便根据评论家的建议将我的部分答案纳入评论中。我将悬赏金授予Ira Baxter积极参与讨论,尽管我尚未确信他是对的:Mark Ransom和Emilio M Bumachar似乎支持我的想法,即在实践中可能进行更正。可能在大多数情况下会产生“正确”的结果。
我仍然必须进行实验以查看结果正确的频率,并且我完全打算这样做,但是我可以花时间的时间有限,因此我还没有解决这个问题。实验并非无关紧要。
没有找到相关结果
已邀请:
8 个回复
冕偷淮款
吐兄
诫商
犁攀富
。 epsilon的另一个定义是浮点数最大的舍入误差。此定义应为第一个定义的一半。 从理论上讲,在四舍五入之前添加一个epsilon值将产生与其校正一样多的错误。实际上,情况并非如此,因为接近偶数的数字比随机机会提示的数字更有可能被遇到。
济畦刨
目浆搽
琶竞捆栓
陈獭
回调模块:
更改为Float即可实际完成工作:
编辑:使用Rational更好。 nmethods重写仍然不总是有效(请参阅代码后的问题):
问题:至少在1.9.3p0中,并非所有方法重写都有效: