C的基本原理:double变量不等于double表达式吗? [英] C fundamentals: double variable not equal to double expression?
问题描述
我正在使用一个名为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语言中,类型float
和double
的表达式实际上被评估为float_t
或double_t
,它们与float
和double
的关系反映在FLT_EVAL_METHOD
宏中.在x86的情况下,两者都定义为long double
,因为fpu实际上不能以单精度或双精度执行算术. (它具有允许这样做的模式位,但行为略有错误,因此无法使用.)
分配给类型float
或double
的对象是强制舍入并摆脱多余精度的一种方法,但是如果您希望将其保留为(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屋!