C基础知识:双变量不等于双表达式? [英] C fundamentals: double variable not equal to double expression?

查看:11
本文介绍了C基础知识:双变量不等于双表达式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用一个名为 indata 的双精度数组(在堆中,使用 malloc 分配)和一个名为 sum 的本地双精度.

I am working with an array of doubles called indata (in the heap, allocated with malloc), and a local double called sum.

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

I wrote two different functions to compare values in indata, and obtained different results. Eventually I determined that the discrepancy was due to one function using an expression in a conditional test, and the other function using a local variable in the same conditional test. I expected these to be equivalent.

我的函数 A 使用:

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

我的函数 B 使用:

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

经过相同的数据集和 max 后,我最终会得到不同的 hi 值,具体取决于我使用的函数.我相信功能 B 是正确的,而功能 A 具有误导性.同样,当我尝试下面的代码段时

After going through the same data set and max, I end up with different values of hi depending on which function I use. I believe function B is correct, and function A is misleading. Similarly when I try the snippet below

    sum = indata[i]+indata[j];
    if ((indata[i]+indata[j]) != sum) etc.

该条件将评估为真.

虽然我知道浮点数不一定能提供精确的表示,但为什么当作为表达式评估而不是存储在变量中时,这种不精确的表示会发生变化?推荐的最佳做法是在条件之前始终评估这样的双重表达式吗?谢谢!

While I understand that floating point numbers do not necessarily provide an exact representation, why does that in-exact representation change when evaluated as an expression vs stored in a variable? Is recommended best practice to always evaluate a double expression like this prior to a conditional? Thanks!

推荐答案

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

I suspect you're using 32-bit x86, the only common architecture subject to excess precision. In C, expressions of type float and double are actually evaluated as float_t or double_t, whose relationships to float and double are reflected in the FLT_EVAL_METHOD macro. In the case of x86, both are defined as long double because the fpu is not actually capable of performing arithmetic at single or double precision. (It has mode bits intended to allow that, but the behavior is slightly wrong and thus can't be used.)

分配给 floatdouble 类型的对象是强制舍入和消除多余精度的一种方法,但您也可以添加一个无偿的强制转换(double) 如果您希望将其保留为不带赋值的表达式.

Assigning to an object of type float or double is one way to force rounding and get rid of the excess precision, but you can also just add a gratuitous cast to (double) if you prefer to leave it as an expression without assignments.

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

Note that forcing rounding to the desired precision is not equivalent to performing the arithmetic at the desired precision; instead of one rounding step (during the arithmetic) you now have two (during the arithmetic, and again to drop unwanted precision), and in cases where the first rounding gives you an exact-midpoint, the second rounding can go in the 'wrong' direction. This issue is generally called double rounding, and it makes excess precision significantly worse than nominal precision for certain types of calculations.

这篇关于C基础知识:双变量不等于双表达式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆