防止舍入误差

3

我刚刚在阅读关于C++中的舍入误差。因此,如果我正在编写一个数学密集型程序(或任何重要的计算),我是否应该完全放弃浮点数,只使用双精度,或者有更简单的方法来防止舍入误差?


2
这是什么数学密集型程序?数学密集并不意味着你需要防止这种浮点错误。 - R. Martinho Fernandes
5
使用双精度浮点数并不能防止舍入误差。 - Mat
@Martinho,当客户期望得到准确性至少近乎的东西时,我会做到>_>。 - Freesnöw
@Mat:此外,几乎任何合理的现代架构都会将您的浮点数提升为双精度,所以为什么还要使用浮点数呢?(除了旧版CUDA之外)OP:如果您需要保证精度,请使用多精度库,例如MPFR。 - Kerrek SB
7
你需要明确定义准确性要求,并对你正在实现的算法有深入的了解,以及它对舍入误差(也称为数值稳定性)有多敏感。 - Paul R
那么,这是金钱吗?还是从某个地方测量出来的数据?或者别的什么?不知道的话,这很难回答。“至少几乎准确”是一个非常模糊的定义。 - R. Martinho Fernandes
3个回答

8

必读课程:每个程序员都应该了解浮点运算

此外,尝试阅读IEEE浮点标准

您总会遇到舍入误差。除非使用类似于GMP库这样的无限任意精度库。您必须决定您的应用程序是否真正需要这种努力。

或者,您可以使用整数算术,在需要时仅转换为浮点数。这仍然很难做到,您必须决定它是否值得。

最后,您可以使用floatdouble,但要注意不要对表示精度极限处的值进行假设。我希望实现了这个Valgrind插件(搜索浮点数)......


1
吹毛求疵: 不是"无限大",而是"任意大小" (一个自然数可以具有任意的大小,但不能具有无限的大小)。 - Kerrek SB

1

舍入误差通常非常微不足道,即使是使用浮点数。像游戏这样的数学密集型程序,即使进行大量的浮点计算,通常仍然使用单精度。


6
游戏对于浮点数的精度并不是那么重要。如果一个精灵向右移动了1个像素,用户不会有任何意见。但是,如果您的软件是空中交通管制系统,一个错误可能会导致一架飞机坠毁。 - Mihai Maruseac
1
你的逻辑可能是反过来的,甚至可能是因为他们执行了很多操作,而不是舍入误差微不足道,所以他们使用单精度。 - Benjamin Bannier

0

如果您的最大数字小于100亿,并且您正在使用C++双精度,则此方法可能有效。

if ( ceil(10000*(x + 0.00001)) > ceil(100000*(x - 0.00001))) { 
    x = ceil(10000*(x + 0.00004)) / 10000; 
}

这应该允许最后一位数字偏差+/-9。我假设除以1000总是只会移动小数点。如果不是,那么可能可以用二进制来实现。

您必须在每个不是+、-、*或比较的操作之后应用它。例如,您不能在同一个公式中进行两次除法,因为您必须将其应用于每个除法。

如果这样不起作用,您可以通过将数字缩放并始终使用整数除法来工作。如果您需要高级函数,也许有一个包可以进行确定性整数运算。由于舍入误差容易被利用,所以在许多金融环境中需要使用整数除法,就像电影《办公室》中一样。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接