void main()
{
float f = 0.98;
if(f <= 0.98)
printf("hi");
else
printf("hello");
getch();
}
我在这里遇到了这个问题。在使用 fi 的不同浮点值时会得到不同的结果。为什么会这样?
void main()
{
float f = 0.98;
if(f <= 0.98)
printf("hi");
else
printf("hello");
getch();
}
我在这里遇到了这个问题。在使用 fi 的不同浮点值时会得到不同的结果。为什么会这样?
f
是使用float
精度,但默认是0.98的double
精度,所以语句f <= 0.98
是使用double
精度进行比较的。
因此,在比较中将f
转换为 a double
,但可能会使结果略大于 0.98。
利用
if(f <= 0.98f)
或使用double
forf
代替。
详细...假设float
是IEEE 单精度并且double
是IEEE 双精度。
这些类型的浮点数以 base-2 表示形式存储。在 base-2 中,这个数字需要无限精度来表示,因为它是一个重复的小数:
0.98 = 0.1111101011100001010001111010111000010100011110101110000101000...
Afloat
只能存储 24 位有效数字,即
0.111110101110000101000111_101...
^ round off here
= 0.111110101110000101001000
= 16441672 / 2^24
= 0.98000001907...
Adouble
可以存储 53 位有效数字,所以
0.11111010111000010100011110101110000101000111101011100_00101000...
^ round off here
= 0.11111010111000010100011110101110000101000111101011100
= 8827055269646172 / 2^53
= 0.97999999999999998224...
所以 0.98 在 中会变得稍微大一点,在 中会变小float
一点double
。
这是因为浮点值不是数字的精确表示。所有以十为底的数字都需要在计算机上表示为以 2 为底的数字。正是在这种转换中,精度丢失了。
在http://en.wikipedia.org/wiki/Floating_point阅读更多相关信息
一个例子(来自我在VB6天遇到这个问题)
要将数字 1.1 转换为单精度浮点数,我们需要将其转换为二进制。有 32 位需要创建。
第 1 位是符号位(是负数 [1] 还是位置 [0]) 第 2-9 位是指数值 第 10-32 位是尾数(又名有效数,基本上是科学计数法的系数)
因此,对于 1.1,单个浮点值存储如下(这是截断值,编译器可能会在后台舍入最低有效位,但我所做的只是截断它,这稍微不太准确,但不会改变结果这个例子):
s --exp--- -------mantissa--------
0 01111111 00011001100110011001100
如果您注意到尾数中有重复模式 0011。二进制的 1/10 就像十进制的 1/3。它永远持续下去。因此,要从 32 位单精度浮点值中检索值,我们必须首先将指数和尾数转换为十进制数,以便我们可以使用它们。
符号 = 0 = 正数
指数:01111111 = 127
尾数:00011001100110011001100 = 838860
使用尾数,我们需要将其转换为十进制值。原因是二进制数前面有一个隐含的整数(即 1.00011001100110011001100)。隐含的数字是因为尾数表示要在科学计数法中使用的标准化值:1.0001100110011.... * 2^(x-127)。
为了得到 838860 的十进制值,我们只需除以 2^-23,因为尾数中有 23 位。这给了我们 0.099999904632568359375。将隐含的 1 添加到尾数中得到 1.099999904632568359375。指数是 127,但公式需要 2^(x-127)。
所以这里是数学:
(1 + 099999904632568359375) * 2^(127-127)
1.099999904632568359375 * 1 = 1.099999904632568359375
如您所见,1.1 并没有真正存储为 1.1 的单浮点值。