C 基础知识:double 变量不等于 double 表达式?
C fundamentals: double variable not equal to double expression?
我正在使用一个名为 indata
的双精度数组(在堆中,使用 malloc 分配)和一个名为 sum
的本地双精度数组。
我写了两个不同的函数来比较indata
中的值,得到了不同的结果。最终我确定差异是由于一个函数在条件测试中使用表达式,而另一个函数在同一条件测试中使用局部变量。我希望这些是等效的。
我的函数 A 使用:
if (indata[i]+indata[j] > max) hi++;
我的函数 B 使用:
sum = indata[i]+indata[j];
if (sum>max) hi++;
经过相同的数据集和 max
后,根据我使用的函数,我最终得到不同的 hi
值。我相信函数 B 是正确的,而函数 A 具有误导性。同样,当我尝试下面的代码片段时
sum = indata[i]+indata[j];
if ((indata[i]+indata[j]) != sum) etc.
该条件将计算为真。
虽然我知道浮点数不一定提供精确的表示,但为什么当作为表达式求值与存储在变量中时,这种不精确的表示会发生变化?推荐的最佳做法是始终在条件之前评估这样的双表达式吗?谢谢!
我怀疑您使用的是 32 位 x86,这是唯一受制于超精度 的常见架构。在 C 中,类型 float
和 double
的表达式实际上被计算为 float_t
或 double_t
,它们与 float
和 double
的关系反映在FLT_EVAL_METHOD
宏。在 x86 的情况下,两者都定义为 long double
,因为 fpu 实际上不能以单精度或双精度执行算术运算。 (它有旨在允许这样做的模式位,但行为略有错误,因此不能使用。)
分配给类型为 float
或 double
的对象是一种强制舍入并消除多余精度的方法,但您也可以只向 [=20= 添加无偿强制转换] 如果您希望将其保留为没有赋值的表达式。
请注意,强制舍入到所需精度并不等同于以所需精度执行算术;而不是一个舍入步骤(在算术过程中)你现在有两个(在算术过程中,再次降低不需要的精度),并且在第一次舍入给你一个精确的中点的情况下,第二次舍入可以进入 'wrong'方向。这个问题通常被称为双舍入,它使某些类型的计算的超精度明显低于标称精度。
我正在使用一个名为 indata
的双精度数组(在堆中,使用 malloc 分配)和一个名为 sum
的本地双精度数组。
我写了两个不同的函数来比较indata
中的值,得到了不同的结果。最终我确定差异是由于一个函数在条件测试中使用表达式,而另一个函数在同一条件测试中使用局部变量。我希望这些是等效的。
我的函数 A 使用:
if (indata[i]+indata[j] > max) hi++;
我的函数 B 使用:
sum = indata[i]+indata[j];
if (sum>max) hi++;
经过相同的数据集和 max
后,根据我使用的函数,我最终得到不同的 hi
值。我相信函数 B 是正确的,而函数 A 具有误导性。同样,当我尝试下面的代码片段时
sum = indata[i]+indata[j];
if ((indata[i]+indata[j]) != sum) etc.
该条件将计算为真。
虽然我知道浮点数不一定提供精确的表示,但为什么当作为表达式求值与存储在变量中时,这种不精确的表示会发生变化?推荐的最佳做法是始终在条件之前评估这样的双表达式吗?谢谢!
我怀疑您使用的是 32 位 x86,这是唯一受制于超精度 的常见架构。在 C 中,类型 float
和 double
的表达式实际上被计算为 float_t
或 double_t
,它们与 float
和 double
的关系反映在FLT_EVAL_METHOD
宏。在 x86 的情况下,两者都定义为 long double
,因为 fpu 实际上不能以单精度或双精度执行算术运算。 (它有旨在允许这样做的模式位,但行为略有错误,因此不能使用。)
分配给类型为 float
或 double
的对象是一种强制舍入并消除多余精度的方法,但您也可以只向 [=20= 添加无偿强制转换] 如果您希望将其保留为没有赋值的表达式。
请注意,强制舍入到所需精度并不等同于以所需精度执行算术;而不是一个舍入步骤(在算术过程中)你现在有两个(在算术过程中,再次降低不需要的精度),并且在第一次舍入给你一个精确的中点的情况下,第二次舍入可以进入 'wrong'方向。这个问题通常被称为双舍入,它使某些类型的计算的超精度明显低于标称精度。