我正在使用一个名为$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存储在变量中时,精确表示会发生变化?建议的最佳做法是在条件之前始终评估这样的双重表达式吗?谢谢!
答案 0 :(得分:12)
我怀疑你使用的是32位x86,这是唯一受多余精度影响的常见架构。在C中,float
和double
类型的表达式实际上被评估为float_t
或double_t
,其与float
和double
的关系反映在FLT_EVAL_METHOD
宏。在x86的情况下,两者都定义为long double
,因为fpu实际上不能以单精度或双精度执行算术。 (它具有允许的模式位,但行为略有错误,因此无法使用。)
分配给float
或double
类型的对象是强制舍入并消除多余精度的一种方法,但是你也可以添加一个无偿的强制转换为(double)
如果你喜欢把它留作没有作业的表达。
请注意,强制舍入到所需的精度并不等于以所需的精度执行算术;而不是一个舍入步骤(在算术期间)你现在有两个(在算术期间,并再次降低不需要的精度),并且在第一个舍入给你一个精确中点的情况下,第二个舍入可以进入'错误'方向。此问题通常称为双舍入,对于某些类型的计算,它会使精度过高,明显低于标称精度。