浮点数相等 [英] Floating point equality

查看:96
本文介绍了浮点数相等的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

众所周知,比较浮点值时必须小心.通常,我们不使用==,而是使用一些基于epsilon或ULP的相等性测试.

但是,我想知道是否有任何情况,使用==完全可以吗?

看看这个简单的代码片段,可以保证成功的情况是什么?

void fn(float a, float b) {
    float l1 = a/b;
    float l2 = a/b;

    if (l1==l1) { }        // case a)
    if (l1==l2) { }        // case b)
    if (l1==a/b) { }       // case c)
    if (l1==5.0f/3.0f) { } // case d)
}

int main() {
    fn(5.0f, 3.0f);
}

注意:我已经检查了当前标准草案中找到的唯一相关声明. :

浮点类型的值表示形式是实现定义的. [注:本文档对浮点运算的准确性没有任何要求;另请参见[support.limits]. —注释]

那么,这是否意味着甚至定义了案例a)"?我的意思是,l1==l1绝对是浮点运算.因此,如果实现是不准确的",那么l1==l1可能为假吗?


我认为这个问题与不是浮点==永远可以吗?.这个问题没有解决我要问的任何情况.相同的主题,不同的问题.我想针对情况a)-d)专门找到答案,为此我无法在重复的问题中找到答案.

解决方案

但是,我想知道是否有任何情况,当使用==完全可以吗?

当然有.一类示例是不涉及计算的用法,例如只能在更改时执行的设置器:

void setRange(float min, float max)
{
    if(min == m_fMin && max == m_fMax)
        return;

    m_fMin = min;
    m_fMax = max;

    // Do something with min and/or max
    emit rangeChanged(min, max);
}

另请参见 浮点==可以吗? 是浮点==曾经好吗? .

It is common knowledge that one has to be careful when comparing floating point values. Usually, instead of using ==, we use some epsilon or ULP based equality testing.

However, I wonder, are there any cases, when using == is perfectly fine?

Look at this simple snippet, which cases are guaranteed to succeed?

void fn(float a, float b) {
    float l1 = a/b;
    float l2 = a/b;

    if (l1==l1) { }        // case a)
    if (l1==l2) { }        // case b)
    if (l1==a/b) { }       // case c)
    if (l1==5.0f/3.0f) { } // case d)
}

int main() {
    fn(5.0f, 3.0f);
}

Note: I've checked this and this, but they don't cover (all of) my cases.

Note2: It seems that I have to add some plus information, so answers can be useful in practice: I'd like to know:

  • what the C++ standard says
  • what happens, if a C++ implementation follows IEEE-754

This is the only relevant statement I found in the current draft standard:

The value representation of floating-point types is implementation-defined. [ Note: This document imposes no requirements on the accuracy of floating-point operations; see also [support.limits]. — end note ]

So, does this mean, that even "case a)" is implementation defined? I mean, l1==l1 is definitely a floating-point operation. So, if an implementation is "inaccurate", then could l1==l1 be false?


I think this question is not a duplicate of Is floating-point == ever OK?. That question doesn't address any of the cases I'm asking. Same subject, different question. I'd like to have answers specifically to case a)-d), for which I cannot find answers in the duplicated question.

解决方案

However, I wonder, are there any cases, when using == is perfectly fine?

Sure there are. One category of examples are usages that involve no computation, e.g. setters that should only execute on changes:

void setRange(float min, float max)
{
    if(min == m_fMin && max == m_fMax)
        return;

    m_fMin = min;
    m_fMax = max;

    // Do something with min and/or max
    emit rangeChanged(min, max);
}

See also Is floating-point == ever OK? and Is floating-point == ever OK?.

这篇关于浮点数相等的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆