我正在使用一个名为 indata
的 double 组(在堆中,使用 malloc 分配)和一个名为 sum
的本地 double 组。
我写了两个不同的函数来比较 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.
该条件将评估为真。
虽然我知道 float 不一定提供精确的表示,但为什么当作为表达式计算而不是存储在变量中时,这种不精确的表示会发生变化?推荐的最佳做法是始终在条件之前评估这样的双表达式吗?谢谢!
最佳答案
我怀疑您使用的是 32 位 x86,这是唯一受制于超精度 的常见架构。在 C 中,float
和 double
类型的表达式实际上被计算为 float_t
或 double_t
,它们与 float
和 double
反射(reflect)在 FLT_EVAL_METHOD
宏中。在 x86 的情况下,两者都被定义为 long double
,因为 fpu 实际上不能以单精度或 double 执行算术运算。 (它有旨在允许这样做的模式位,但行为略有错误,因此不能使用。)
分配给 float
或 double
类型的对象是一种强制舍入并消除多余精度的方法,但您也可以只添加一个无偿强制转换(double)
如果您希望将其保留为没有赋值的表达式。
请注意,强制舍入到所需精度并不等同于以所需精度执行算术;而不是一个舍入步骤(在算术过程中)你现在有两个(在算术过程中,再次降低不需要的精度),并且在第一次舍入给你一个精确的中点的情况下,第二次舍入可以进入“错误的” ' 方向。这个问题通常被称为双舍入,对于某些类型的计算,它会使超额精度明显低于标称精度。
关于C 基础知识 : double variable not equal to double expression?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37626687/