C 中浮点数的比较

发布于 2024-11-28 23:33:35 字数 124 浏览 6 评论 0原文

我有一个 double 打印为 0.000000,我试图将它与 0.0f 进行比较,但没有成功。为什么这里有区别呢?确定双精度数是否为零的最可靠方法是什么?

I've got a double that prints as 0.000000 and I'm trying to compare it to 0.0f, unsuccessfully. Why is there a difference here? What's the most reliable way to determine if your double is zero?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

很酷又爱笑 2024-12-05 23:33:35

为了确定它是否足够接近零,以至于它将打印为小数点后六位的 0.000000,例如:

fabs(d) < 0.0000005

不过,处理浮点计算中的小误差通常会变得相当复杂。

如果您想更好地了解自己获得的值,请尝试使用 %g 而不是 %f 进行打印。

To determine whether it's close enough to zero that it will print as 0.000000 to six decimal places, something like:

fabs(d) < 0.0000005

Dealing with small inaccuracies in floating-point calculations can get quite complicated in general, though.

If you want a better idea what value you've got, try printing with %g instead of %f.

还不是爱你 2024-12-05 23:33:35

你可以做一个范围。就像-0.00001 <= x <= 0.00001

You can do a range. Like -0.00001 <= x <= 0.00001

臻嫒无言 2024-12-05 23:33:35

这是现代计算机上浮点运算的基本问题。它们本质上是不精确的,并且无法可靠地进行比较。例如,ML 语言明确不允许对实际类型进行相等比较,因为它被认为太不安全。另请参阅 David Goldberg 撰写的优秀论文(虽然有点长且以数学为导向)论文话题。

编辑:tl;dr:你可能做错了。

This is fundamental problem with floating point arithmetic on modern computers. They are by nature imprecise, and cannot be reliably compared. For example, the language ML explicitly disallows equality comparison on real types because it was considered too unsafe. See also the excellent (if a bit long and mathematically oriented) paper by David Goldberg on this topic.

Edit: tl;dr: you might be doing it wrong.

赠佳期 2024-12-05 23:33:35

此外,浮点数的一个经常被忽视的特征是非规范化数。
这些数字具有最小指数,但不在 0.5-1 范围内。

这些数字低于浮点型的 FLT_MIN 和双精度型的 DBL_MIN。

使用阈值的一个常见错误是比较两个值,或使用 FLT_MIN/DBL_MIN 作为限制。

例如,这会导致不合逻辑的结果(如果您不了解非正规化):

bool areDifferent(float a, float b) {
    if (a == b) return false;  // Or also: if ((a - b) == FLT_MIN) 
    return true;
}


// What is the output of areDifferent(val, val + FLT_MIN * 0.5f) ?
// true, not false, even if adding half the "minimum value".

非正规化通常还意味着计算性能损失。
然而,您不能禁用它们,否则此类代码仍可能产生 DIVIDE BY ZERO 浮点异常(如果启用):

float getInverse(float a, float b) {
    if (a != b)
        return 1.0f / (a-b); // With denormals disabled, a != b can be true, but (a - b) can still be denormals, it'll rounded to 0 and throw the exception
    return FLT_MAX;
}

Also, one often overlooked features of floating point number are the denormalized numbers.
That's numbers which have the minimal exponent, yet don't fit in the 0.5-1 range.

Those numbers are lower than FLT_MIN for float, and DBL_MIN for double.

A common mistake with using a threshold is to compare two values, or use FLT_MIN/DBL_MIN as limit.

For example, this would lead unlogical result (if you don't know about denormals):

bool areDifferent(float a, float b) {
    if (a == b) return false;  // Or also: if ((a - b) == FLT_MIN) 
    return true;
}


// What is the output of areDifferent(val, val + FLT_MIN * 0.5f) ?
// true, not false, even if adding half the "minimum value".

Denormals also usually implies a performance loss in computation.
Yet, you can not disable them, else such code could still produce a DIVIDE BY ZERO floating point exception (if enabled):

float getInverse(float a, float b) {
    if (a != b)
        return 1.0f / (a-b); // With denormals disabled, a != b can be true, but (a - b) can still be denormals, it'll rounded to 0 and throw the exception
    return FLT_MAX;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文