以下代码的输出为0.0000000
:
#include <stdio.h>
int main() {
float x;
x = (float)3.3 == 3.3;
printf("%f", x);
return 0;
}
此代码输出1.000000
:
int main() {
float x;
x = (float)3.5 == 3.5;
printf("%f", x);
return 0;
}
这两个代码之间的唯一区别是比较中的值,但是结果不一样,为什么呢?
答案 0 :(得分:5)
此行:
x=(float)3.3==3.3;
比较(float)3.3
和3.3
的相等性,并将结果分配给x
。由于类型转换,比较的左侧类型为float
,而右侧的类型为double
,这是浮点常量的默认类型。
值3.3不能精确地用二进制浮点数表示,因此存储的实际值只是一个近似值。由于类型float
和double
的精度不同,该近似值将有所不同,因此相等性将被评估为false,即0。这是分配给x
的值。
关于当您检查的数字为3.5时x
为什么为1的评论,这是因为3.5 可以精确地用二进制表示,并且两种类型的精度都可以存储该值,以便它们比较相等。
答案 1 :(得分:2)
分配的值3.3
是double
的类型,但是您试图将double
与float
进行比较(通过类型转换,因此,精度损失)。
3.3
与double
的值是3.299999999999999822,而float
中相同的值被测量为3.299999952F,这显然是不相等的。因此,如果您将其他3.3
键入为float
,则结果将为true(即1.0000000)。
而不是:
x = (float) 3.3 == 3.3; // float != double precision (precision loss)
如果您这样做:
x = (float) 3.3 == (float) 3.3; // converting both to make precision equal
或者,
x = (double) 3.3 == (double) 3.3; // converting . . . (same)
换句话说,如果将任何一个表达式转换为另一个表达式,则比较将相等。
此外,请注意,3.5
和float
中的double
等于3.50000000 ...,因此,所有尾随零都从分配的变量中被截断,因此得到1.0000000。但这与3.3
有点相反。
答案 2 :(得分:2)
float
的精度低于double
,3.3
常量的值默认为double,并且为3.299999999999999822
,即转换为float
is 3.29999995231628418
时的常量。
3.299999999999999822 == 3.29999995231628418
的比较结果是false
,即0
。
给定优先级规则,表示等于x = ((float)3.5 == 3.5);
,首先评估比较并将结果分配给x
。
当没有强制转换时,两个常量默认为double
,因此它们之间的比较结果自然是true
,即1
。
关于3.5
double
和float
为true
之间的比较,它与the binary conversion有关,3.3
受到考虑到link above中可以看到尾数转换将无限期地进行的事实,确切的值根本无法用double
或float
表示,而{{1} }可以完美地代表in double
和float
alike。
答案 3 :(得分:1)
要查看float导致的精度损失:
#include <stdio.h>
int main(){
float x = 3.3;
double d = 3.3;
printf("%12.9f %12.9lf\n",x, d);
输出:
3.299999952 3.300000000
答案 4 :(得分:1)
3.3二进制是
11.0100110011001100110011001100110011001100110011
转换为float
时,一些精度会被截断
11.0100110011001100110011001100110
转换回两倍后,计算机仅使用0
的
11.0100110011001100110011001100110000000000000000
所以
3.3 11.0100110011001100110011001100110011001100110011
(float)3.3 11.0100110011001100110011001100110
(double)((float)3.3) 11.0100110011001100110011001100110000000000000000
3.5进行比较
3.5 11.1000000000000000000000000000000000000000000000
(float)3.5 11.1000000000000000000000000000000
(double)((float)3.5) 11.1000000000000000000000000000000000000000000000
答案 5 :(得分:1)
像3.3
这样的值不能用有限数量的位精确地表示,就像1/3
的结果不能精确地用有限数量的十进制数表示一样,因此您最终会存储一个近似值。
float
近似与double
近似不同,因此比较(float) 3.3 == 3.3
失败。
相反,3.5
可以精确地用float
和double
类型表示,因此比较(float) 3.5 == 3.5
成功。
就像整数类型一样,浮点类型的有效位数是2的幂的和-值3.5
表示为1.75 * 21
,而二进制数表示有效位数{{ 1}}是1.75
-1.112
或1 * 20 + 1 * 2-1 + 1 * 2-2
。
答案 6 :(得分:0)
问题在于,将类型为3.3
的文字类型的值double
转换为强制类型为(float)3.3
的浮点值时,会降低精度。即使比较运算符==
将左操作数提升为double类型,这种精度损失也是不可逆的。
所以问题在于
(double)((float)3.3) == (double)3.3
为假,因为将3.3
强制转换为float
会降低精度。相比之下,对于3.5
,结果将是true
,因为3.5可以精确地表示为float
,而精度与double
相同。
实际上,可以将情况与将值从较高的等级转换为较低的值,然后像下面的代码片段中返回那样进行比较:
unsigned int x = 257;
unsigned char y = x;
unsigned int x2 = y;
printf("%d\n", x==x2); // 0
x = 255;
y = x;
x2 = y;
printf("%d\n", x==x2); // 1