Con*_*ion 10 floating-point precision rounding
我想知道,在特定条件下,是否可以在不使用任意精度数据类型的情况下删除浮点错误.
问题是通常的问题.语言是Ruby,但它包含在任何语言中:
f = 1829.82
=> 1829.82
f / 12.0
=> 152.485
(f / 12.0).round(2)
=> 152.48
Run Code Online (Sandbox Code Playgroud)
为什么不是152.49?因为浮点的精度有限:
format("%18.14f", f)
=> "1829.81999999999994"
format("%18.14f", f / 12.0)
=> "152.48499999999999"
Run Code Online (Sandbox Code Playgroud)
所以四舍五入是正确的.现在的问题是:有没有办法让我想反正答案,给出的下列情况:有上(数)业务强劲限制使用浮动进行的,所需要的精确度是有限的到小数点后两位(最多8个位数总共)和少量剩余的"错误"圆形答案是可以接受的吗?
用户可以输入有效的Ruby字符串,例如:
"foo / 12.0"
Run Code Online (Sandbox Code Playgroud)
其中foo是在执行字符串的上下文中提供的数字,但其中'12 .0'是用户输入的内容.想象一下带有一些免费公式字段的电子表格.字符串简单地被评估为Ruby,因此12.0变为Float.我可以使用ruby_parser + ruby2ruby gems构建一个解析树,将数据类型转换为Bignum,Rational,来自Flt库的东西,十进制浮点表示或者你有什么,但这很棘手,因为实际的字符串可以变成有点复杂,所以我不想这样做.如果没有其他可能的话,我会这样做,但这个问题是专门在这里看看我是否可以避开这条道路.因此,12.0的数据类型是严格Float和结果严格Float和我能做的唯一的事情是解释片段的最终答案,并试图"纠正"它,如果它四舍五入"错误"的方式.
用户唯一的计算涉及精度为两位小数的数字(总共最多8位).使用'simple'我的意思是浮点错误没有机会累积:我可以添加其中两个数字并将一个除以整数,但随后计算完成,结果舍入并存储并随后进行计算基于该舍入数字.通常只有一个浮点错误都会涉及,但我认为问题并不显著改变,如果两者可以积累,但残留的错误率可能是通过定义较大.
首先想到的是首先舍入到3位小数,然后是2位.但是,这不起作用.这将导致
152.48499999999999 => 152.485 => 152.49
Run Code Online (Sandbox Code Playgroud)
但是也
152.4846 => 152.485 => 152.49
Run Code Online (Sandbox Code Playgroud)
这不是你想要的.
接下来我想到的是将最小可能的增量(如人们已经指出的,取决于所考虑的浮点值)添加到浮点数(如果它在.5边界上轻推它).我主要想知道这可能导致"误报"的频率:添加最小增量的数字,即使它刚好低于.5边界的事实不是由于浮点错误,但是因为这只是计算的结果?
第二个选择是:只要永远的最小增量增加的数字,因为.5地区是唯一一个在那里也无妨重要.
编辑:我刚刚重写了问题,将我的部分答案纳入评论中,正如cdiggins建议的那样.我将奖励给了Ira Baxter积极参与讨论,尽管我还不确定他是对的:Mark Ransom和Emilio M Bumachar似乎支持我的观点,即在实践中,可能会进行修正相对大多数情况下,会产生"正确"的结果.
我仍然需要进行实验,看看结果是多么频繁,我完全打算这样做,但是我可以花在这上面的时间有点受限,所以我还没有完成它.这个实验并非无足轻重.
"有可能在不诉诸无限精度数据类型的情况下删除浮点错误."?
不会.浮点错误是计算机唯一涉及数字运算的错误.如果删除所有错误,根据定义,您的精度是无限的.
这听起来很迂腐,这不是我的意图.我想指出在你明显的技术问题下面存在一个很大的概念问题.除非您知道它们的正确值(即无限精度值或承载该信息的其他形式),否则您无法根据其正确值来正确舍入错误数字.
您添加少量数字的想法可能会在统计上得出结论,但仅限于统计数据.我建议你写一个脚本来测试大量的案例,随机数不超过两位小数.(脚本还需要以无限精度进行数学运算,以便知道正确的比较答案)这样,您就可以测量校正和误报.
| 归档时间: |
|
| 查看次数: |
3013 次 |
| 最近记录: |