了解浮点问题

Posted

技术标签:

【中文标题】了解浮点问题【英文标题】:Understanding floating point problems 【发布时间】:2011-06-07 13:43:04 【问题描述】:

这里有人可以帮助我了解如何确定浮点限制何时会导致计算错误。比如下面的代码。

CalculateTotalTax = function (TaxRate, TaxFreePrice) 
     return ((parseFloat(TaxFreePrice) / 100) * parseFloat(TaxRate)).toFixed(4);
;

我无法输入任何两个值,这导致此方法的结果不正确。如果我删除 toFixed(4) ,我实际上可以看到计算开始失去准确性的位置(大约在小数点后 6 位左右)。尽管如此,我对浮点数的理解是,即使是很小的数字有时也可能无法表示或我误解了,并且总是可以准确地表示 4 位小数(例如)。

MSDN 将浮点数解释为 such...

这意味着他们无法准确掌握 任何数量的表示 不是二进制分数(形式为 k / (2 ^ n) 其中 k 和 n 是整数)

现在我假设这适用于所有浮点数(包括 javascript 中使用的浮点数)。

基本上我的问题归结为这一点。如何确定任何特定方法是否容易受到浮点运算错误的影响,这些错误将以什么精度实现以及产生这些错误需要哪些输入?

希望我的问题是有道理的。

【问题讨论】:

可能跟这个话题有关:en.wikipedia.org/wiki/Machine_epsilon 小马托尼,也称为Jon Skeet,有一个excellent explanation。易读、清晰、有趣且不刺激,而且不像经常在此主题上发布的 some links 那样沉重。 【参考方案1】:

首先阅读每位计算机科学家都应该了解的浮点知识: http://docs.sun.com/source/806-3568/ncg_goldberg.html

简短的回答:双精度浮点数(JavaScript 中的默认值)具有大约 16 位十进制数字的精度。舍入可能因平台而异。如果你得到始终如一的正确答案是绝对必要的,你应该自己做理性算术(这并不难 - 对于货币,也许你可以乘以 100 以将美分数存储为整数)。

但如果能以高精度得到答案,浮点数就足够了,尤其是双精度。

【讨论】:

【参考方案2】:

在处理浮点数时,您现在应该做两件重要的事情:

1- 你应该知道machine epsilon。要知道你有多少精度。

2- 你不应该假设if two values are equal in base 10, they are equal in base 2 in a machine with precision limit。

if ((6.0 / 10.0) / 3.0 != .2) 
        cout << "gotcha" << endl;

数字 2 可能足以让您避免比较浮点数是否相等,而是可以使用阈值和大于或小于运算符进行比较

【讨论】:

数字 2 并不意味着您“不应该比较浮点数是否相等”;毕竟,很容易得出你永远不应该比较十进制数的相等性。这意味着一个人不应该编写自己不理解的代码。花点时间了解浮点的工作原理。 正如你所说,学习浮点应该花时间;像 (0.1 == 1/10) 这样的东西看起来很无辜,除非他以前读过它,否则没人会认为它会导致错误。即使谈论数学基础,也没有多少人知道 10 = 9.999.... 或者如何将十进制转换为二进制。 之所以.1 != 1/10是因为1/10 == 0。您正在使用整数除法。 谢谢@Shedal。更正了答案。【参考方案3】:

不,小数位数与可以表示的内容无关。

尝试 0.1 * 3,或 162.295 / 10,或 24.0 + 47.98。那些对我来说在 JS 中失败了。但是,24.0 * 47.98 不会失败。

因此,要回答您的三个问题,任何精度的任何操作都可能容易受到攻击。给定的输入是否会是一个我不知道如何回答的问题,但我有一种预感,有很多因素。 1)实际答案与最接近的二进制分数有多接近。 2) 执行计算的引擎的精度。 3) 用于执行计算的方法(例如,通过位移相乘可能会得到与重复相加相乘不同的结果)

【讨论】:

【参考方案4】:

其他答案指出了理解这个问题的好资源。如果您在代码中实际使用货币值(如您的示例中),您应该更喜欢小数类型(.Net 中的 System.Decimal)。这些将避免使用浮点数导致的一些舍入问题并更好地匹配域。

【讨论】:

以上是关于了解浮点问题的主要内容,如果未能解决你的问题,请参考以下文章

检查字典中的浮点值以了解 Python 中的条件

[ C语言 ]一篇带你了解浮点型在内存中的存储

什么定义了python中的浮点精度?

IEEE-754浮点计算精度问题

GCC 扩展 Asm - 了解 clobbers 和暂存寄存器的使用

浮点数学被破坏了吗?