c++ 双精度浮点数转2进制_关于浮点数的几个有意思的例子

本文都是下面文章开头6个问题的解答:

张雅宸:浮点数的二进制表示以及几个例子​zhuanlan.zhihu.com

问题1

int c = 0.58 * 100;
printf("%dn",c);           //57

int x = 0.58f * 100.0f;
printf("%dn",x);          //58

当两个数字都是float类型时,相乘的结果却是58。揭开谜底的过程涉及了浮点数的存储方式、浮点数的乘法规则和舍入。

关于浮点数的存储方式可以参看浮点数的二进制表示以及几个例子,这里不再赘述。

0.58 * 100

0.58的双精度表示是:
0 01111111110 0010100011110101110000101000111101011100001010001111

100的双精度表示是(浮点数):
0 10000000101 1001000000000000000000000000000000000000000000000000

我们看一下0.58 * 100的计算过程:

转变为标准的科学技术法:

0.58是1.0010100011110101110000101000111101011100001010001111 * 2^-1
100是1.1001000000000000000000000000000000000000000000000000 * 2^6

将两个指数相加

-1 + 6 = 5

将两个尾数相乘

1.0010100011110101110000101000111101011100001010001111 * 1.1001000000000000000000000000000000000000000000000000 =
1.11001111111111111111111111111111111111111111111111110000000000000000000000000000000000000000000000000000

规格化

上面的结果是规格化小数,无需变化(小数点左边只有一个1)

符号位相加mod2

0 + 0 = 0

舍入

重点在这里,由于双精度的位数只有52位,所以我们要舍弃一部分尾数。IEEE默认使用向偶数舍入。所以上面的结果舍入后是:
1.1100111111111111111111111111111111111111111111111111

判断溢出

判断阶码相加是否有溢出。 无

所以最后的结果是
0 10000000100 1100111111111111111111111111111111111111111111111111

结果为:57.999999999999992894572642399

由于C语言中float/double转向整数使用向零靠近,所以最后结果0.58 * 100 = 57。

我们再看一下0.58f * 100.0f的计算过程:

0.58f * 100.0f

0.58的单精度表示是:
0 01111110 00101000111101011100001

100的单精度表示是(浮点数):
0 10000101 10010000000000000000000

具体过程:

转变为标准的科学技术法

0.58是1.00101000111101011100001 * 2^-1
100是1.10010000000000000000000 * 2^6

将两个指数相加

-1 + 6 = 5

将两个尾数相乘

1.00101000111101011100001 * 1.10010000000000000000000 =
1.1100111111111111111111110010000000000000000000

规格化

上面的结果是规格化小数,无需变化(小数点左边只有一个1)

符号位相加mod2

0 + 0 = 0

舍入

由于单精度的位数只有23位,所以我们要舍弃一部分尾数。上面的双精度舍入时是把最后的0全部舍入。但是这里的单精度舍入时,需要进一位。这也是造成两个乘法结果不相等的原因。 所以上面的结果舍入后是:
1.11010000000000000000000

判断溢出

判断阶码相加是否有溢出。 无

所以最后的结果是
0 10000100 11010000000000000000000

结果恰好为58.0。所以0.58f * 100.0f = 58

最后说一下,向偶数舍入和我们学的四舍五入还不太一样。可以看一下浮点数的二进制表示以及几个例子的浮点数舍入部分。

问题2

printf("%d",0.1 + 0.2 == 0.3);        //0,not 1

这个问题涉及到的是浮点数的加法。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值