现在的位置: 首页 > 综合 > 正文

浮点数陷阱

2013年10月02日 ⁄ 综合 ⁄ 共 884字 ⁄ 字号 评论关闭

陷阱1

double i;
for(i = 0; i != 10; i += 0.1)
    printf("%.1lf\n", i);

程序会打印至10.0时结束循环吗?不会。因为i永远也不可能等于10,这是个无限循环

陷阱2

if(0.1+0.1+0.1 == 0.3)
    printf("equal\n");
else
    printf("not equal\n");

会输出"equal"吗?不会。实际浮点数运算时,0.1+0.1+0.1 != 0.3

产生上述陷阱的原因

实际上,计算机中的所有数据都用二进制表示,包括浮点数。这就导致某些浮点数不能用二进制精确表示,例如0.1(这很容易理解,就像10/3不能被十进制精确表示一样

进一步地说,浮点数是采用分数+指数来表示的,例如

0.5 = 1/2

0.75 = 1/2 + 1/(2^2)

0.875 = 1/2 + 1/(2^2) + 1/(2^3)

0.1 = 1/(2^4) + 1/(2^5) + 1/(2^8) + ...

其中0.1只能无限循环下去,这就意味着0.1在计算机中不能被精确表示,因此产生上述两个陷阱也就很容易理解


陷阱1

double i;
for(i = 0; i != 10; i += 0.1)
    printf("%.1lf\n", i);

程序会打印至10.0时结束循环吗?不会。因为i永远也不可能等于10,这是个无限循环

陷阱2

if(0.1+0.1+0.1 == 0.3)
    printf("equal\n");
else
    printf("not equal\n");

会输出"equal"吗?不会。实际浮点数运算时,0.1+0.1+0.1 != 0.3

产生上述陷阱的原因

实际上,计算机中的所有数据都用二进制表示,包括浮点数。这就导致某些浮点数不能用二进制精确表示,例如0.1(这很容易理解,就像10/3不能被十进制精确表示一样

进一步地说,浮点数是采用分数+指数来表示的,例如

0.5 = 1/2

0.75 = 1/2 + 1/(2^2)

0.875 = 1/2 + 1/(2^2) + 1/(2^3)

0.1 = 1/(2^4) + 1/(2^5) + 1/(2^8) + ...

其中0.1只能无限循环下去,这就意味着0.1在计算机中不能被精确表示,因此产生上述两个陷阱也就很容易理解

抱歉!评论已关闭.