鉴于我们对它们没有操作,严格比较浮点数是否安全?

通常,当我们想要测试小数的相等性时,由于IEEE754的近似性质,我们这样做会带来一些不确定性.

if (fabs(one_float - other_float) < SUFFICIENTLY_SMALL) {
    consider them equal;
}

其他方法可能是将浮点数转换为特定幅度的整数,并比较生成的整数.

if ((uint)one_float == (uint)other_float) {
    consider them equal;
}

但考虑一下我们的花车从未经历任何算术的情况,我们唯一能做的就是分配.

//  Might be called at any moment
void resize(float new_width, float new_height)
{
    if (current_width == new_width && current_height == new_height) {
        return;
    }

    accomodate framebuffers;
    update uniforms;
    do stuff;

    current_width = new_width;
    current_height = new_height;
}

在上面的示例中,我们有一个可以自发启动的事件处理程序,我们只想在发生实际调整大小时重新分配资源.我们可能采用通常的路径进行近似比较,但这似乎是一种浪费,因为该处理程序会经常启动.据我所知,浮点数与其他所有内容一样,使用内存移动;和等号运算符只执行内存比较.所以看起来我们处在一个安全的港湾.在x86和ARM上检查时,这个假设成立,但我只想确定.也许它受到一些规格的支持?

那么,只有在分配它们时才有可能改变浮动的东西吗?描述的方法是否可行?

最佳答案 随之而来的是“应该”的大量内容.

我不认为有任何说明从float到float(current_width = new_width)的赋值不能改变该值,但如果存在这样的事情,我会感到惊讶.除了直接复制之外,没有理由在相同类型的变量之间进行分配.

如果传入的new_width和new_height保持其值直到它们发生变化,那么这种比较不应该有任何问题.但是如果在每次调用之前计算它们,它们可能会改变它们的值,这取决于计算的完成方式.因此,不仅需要检查此功能.

C 2011标准表示计算可能使用比您指定的格式更高的精度,但没有具体关于将变量分配给另一个.所以唯一的不精确应该是在计算阶段. “简单分配”部分(6.5.16.1)说:

In simple assignment (=), the value of the right operand is converted to the type of the assignment expression and replaces the value stored in the object designated by the left operand.

因此,如果类型已匹配,则不需要转换.

所以,简单地说:如果你没有在每次调用时重新计算传入值,那么相等的比较应该成立.但是,确实存在一个框架缓冲区大小为浮点数而不是整数的情况吗?

点赞