C基础:双变量不等于双重表达式?

时间:2016-06-04 05:24:45

标签: c syntax floating-point expression floating-accuracy

我正在使用一个名为$data['product_list'][0] = array('prd_id'=>'id0','prd_name'=>'name0'); $data['product_list'][1] = array('prd_id'=>'id1','prd_name'=>'name1'); $data['product_list'][2] = array('prd_id'=>'id2','prd_name'=>'name2'); 的双精度数组(在堆中,使用malloc分配)和一个名为indata的本地双精度数。

我写了两个不同的函数来比较sum中的值,并获得了不同的结果。最终我确定差异是由于一个函数在条件测试中使用表达式,而另一个函数在同一条件测试中使用局部变量。我希望这些是等价的。

我的功能A使用:

indata

我的功能B使用:

    if (indata[i]+indata[j] > max) hi++;

在浏览相同的数据集和 sum = indata[i]+indata[j]; if (sum>max) hi++; 后,我最终会得到max的不同值,具体取决于我使用的是哪个函数。我认为功能B是正确的,功能A是误导性的。同样,当我尝试下面的代码片段时

hi

条件将评估为true。

虽然我理解浮点数不一定能提供精确的表示,但为什么在计算表达式vs存储在变量中时,精确表示会发生变化?建议的最佳做法是在条件之前始终评估这样的双重表达式吗?谢谢!

1 个答案:

答案 0 :(得分:12)

我怀疑你使用的是32位x86,这是唯一受多余精度影响的常见架构。在C中,floatdouble类型的表达式实际上被评估为float_tdouble_t,其与floatdouble的关系反映在FLT_EVAL_METHOD宏。在x86的情况下,两者都定义为long double,因为fpu实际上不能以单精度或双精度执行算术。 (它具有允许的模式位,但行为略有错误,因此无法使用。)

分配给floatdouble类型的对象是强制舍入并消除多余精度的一种方法,但是你也可以添加一个无偿的强制转换为(double)如果你喜欢把它留作没有作业的表达。

请注意,强制舍入到所需的精度并不等于以所需的精度执行算术;而不是一个舍入步骤(在算术期间)你现在有两个(在算术期间,并再次降低不需要的精度),并且在第一个舍入给你一个精确中点的情况下,第二个舍入可以进入'错误'方向。此问题通常称为双舍入,对于某些类型的计算,它会使精度过高,明显低于标称精度。