C的基本原理:double变量不等于double表达式吗? [英] C fundamentals: double variable not equal to double expression?

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

问题描述

我正在使用一个名为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.

该条件将评估为true.

虽然我了解浮点数不一定提供精确的表示形式,但是当将其作为表达式求值与存储在变量中时,为什么不精确的表示形式会发生变化?是否建议最好的最佳实践是始终在条件条件之前评估这样的双重表达式?谢谢!

解决方案

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

分配给类型floatdouble的对象是强制舍入并摆脱多余精度的一种方法,但是如果您希望将其保留为(double),则还可以向(double)添加免费的强制类型转换没有赋值的表达式.

请注意,将舍入强制为所需的精度并不等同于以所需的精度执行算术;而不是一个舍入步骤(在算术过程中),您现在有了两个步骤(在算术过程中,又一次降低了不必要的精度),并且在第一个舍入为您提供精确中点的情况下,第二个舍入会出现错误的情况. ' 方向.这个问题通常称为 double rounding (双舍入),对于某些类型的计算,它会使多余的精度明显低于名义精度.

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

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.

My function A uses:

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

and my function B uses:

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

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.

that conditional will evaluate to true.

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!

解决方案

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.)

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的基本原理:double变量不等于double表达式吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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