浮点数与浮点数相比,奇怪的输出
float f = 0.7; if( f == 0.7 ) printf("equal"); else printf("not equal");
为什么输出not equal
?
为什么会发生?
这是因为在你的陈述
if(f == 0.7)
0.7被视为双倍。 尝试0.7f,以确保该值被视为浮动:
if(f == 0.7f)
但正如Michael在下面的评论中所build议的,你不应该testing浮点值的确切的相等性。
这个答案补充了现有的答案:注意0.7不能完全表示为float(或者double)。 如果它被完全表示出来,那么在转换为浮点数的时候就不会有任何信息丢失,然后回到两倍,而且你不会有这个问题。
甚至可以认为,对于不能准确地表示的文字浮点常量应该有一个编译器警告,特别是当标准对模式中的舍入是否在设置为那个时间或在另一个舍入模式下的编译时间。
所有可以精确表示的非整数都有5
作为最后的小数位。 不幸的是,相反是不正确的:一些数字有5
作为他们的最后一个小数位,不能准确表示。 小整数都可以精确地表示出来,并且除以2的幂除可以把一个可以表示的数字转换成另一个可以表示的数字,只要你不进入非规格化数字的范围。
首先让我们看看浮点数。 我采取0.1f它是4字节长(binary32),在hex是
3D CC CC CD 。
通过标准IEEE 754将其转换为十进制,我们必须这样做:
在二进制3D CC CC CD是
0 01111011 1001100 11001100 11001101
这里的第一个数字是一个符号位。 0意味着(-1)^ 0我们的数字是正数。
第二个8位是一个指数。 在二进制中它是01111011 – 十进制的123.但是真正的指数是123-127(总是127)= -4 ,这意味着我们需要乘以我们将得到的数量2 ^( – 4)。
最后的23个字节是有意义的精度。 第一位乘以1 /(2 ^ 1)(0.5),第二位乘以1 /(2 ^ 2)(0.25),依此类推。 这里我们得到:
我们需要添加所有的数字(2的幂)并添加到1(总是1,通过标准)。 它是
1,60000002384185791015625
现在我们把这个数乘以2 ^( – 4),它来自指数。 我们只是把4以上的数字除以2:
0,100000001490116119384765625
我用MS计算器
**
现在是第二部分。 从十进制转换为二进制。
**
我拿数字0.1
它容易,因为没有整数部分。 第一个符号位 – 它是0.指数和重要性和精度我现在将计算。 逻辑乘以2整数(0.1 * 2 = 0.2),如果大于1,则继续。
而且这个数字是.00011001100110011001100110011,standart说我们必须在得到1之前左移(某事)。 你如何看待我们需要4class,从这个数字计算指数 (127-4 = 123 )。 现在的重要性和精确性是
10011001100110011001100 (有丢失的位)。
现在是整个号码。 符号位0指数为123( 01111011 ),重要性和准确性为10011001100110011001100 ,整体是
00111101110011001100110011001100我们来比较一下前一章的内容
00111101110011001100110011001101
正如你看到的最后一点不相等。 这是因为我截断了这个数字。 CPU和编译器知道这是有意义的,精度不能保持,只是把最后一位设置为1。
正如其他评论者所指出的那样,您所面临的问题是,在浮点数之间进行精确等价testing通常是不安全的,因为初始化错误或计算中的舍入错误可能会导致小的差异,从而导致==运算符返回false。
更好的做法是做类似的事情
float f = 0.7; if( fabs(f - 0.7) < FLT_EPSILON ) printf("equal"); else printf("not equal");
假设FLT_EPSILON已被定义为您的平台适当的小浮点值。
由于四舍五入或初始化错误将不可能超过FLT_EPSILON的值,这将给你你正在寻找的可靠的等效性testing。
考虑这个:
int main() { float a = 0.7; if(0.7 > a) printf("Hi\n"); else printf("Hello\n"); return 0; }
如果(0.7> a)这里a是一个浮点型variables, 0.7
是一个双常数。 双常数0.7
大于浮点型variablesa。 因此,如果条件满足,它打印'Hi'
例:
int main() { float a=0.7; printf("%.10f %.10f\n",0.7, a); return 0; }
输出:
0.7000000000 0.6999999881
networking上的很多答案都会犯这个浮点数之间差别的错误,这只适用于特殊情况,可靠的方法是看下面的相对差异:
// Floating point comparison: bool CheckFP32Equal(float referenceValue, float value) { const float fp32_epsilon = float(1E-7); float abs_diff = std::abs(referenceValue - value); // Both identical zero is a special case if( referenceValue==0.0f && value == 0.0f) return true; float rel_diff = abs_diff / std::max(std::abs(referenceValue) , std::abs(value) ); if(rel_diff < fp32_epsilon) return true; else return false; }