略谈float

我们先来看这样的一段代码:

#include <stdio.h>

void main()
{
	float a = 0;
	for (int i = 0; i < 100; i++)
		a = a + 0.1;
	printf_s("a=%f", a);
	getchar();
}

运行结果如下:


为什么不是10呢?而是10.000002

我们对小数部分:如0.5,0.25,0.125

他们分别表示:2^-1,2^-2,2^-3,

所以对于某些小数不能精确的表示如0.1下面看截图



我们先来看float在内存中的位置


第一个s代表符号为,1代表负数,0代表正数。


第二个域是指数域,对于单精度float类型,指数域有8位,可以表示 0-255个指数值。指数值规定了小数点的位置,小数点的移动代表了所表示数值的大小。但是,指数可以为正数,也可以为负数。为了处理负指数的情况,实际的指数值按要求需要加上一个偏差(Bias)值作为保存在指数域中的值,单精度数的偏差 值为 -127,而双精度double类型的偏差值为 -1023。比如,单精度指数域中的64 则表示实际的指数值 -63。 偏差的引入使得对于单精度数,实际可以表达的指数值的范围就变成-127 到 128 之间(包含两端)。我们不久还将看到,实际的指数值-127(保存为 全 0)以及 +128(保存为全1)保留用作特殊值的处理。这样,实际可以表达的有效指数范围就在 -126 和 +127 之间。


第三个域为尾数域,其中单精度数为 23 位长,双精度数为 52 位长。比如一个单精度尾数域中的值为: 00001001000101010101000, 第二个域中的指数值则规定了小数点在尾数串中的位置,默认情况下小数点位于尾数串首位之前。


下面我们应该如何避免这个问题

1.避免小数计算(代码如下)

#include <stdio.h>

void main()
{
	float a = 0;
	for (int i = 0; i < 100; i++)
		a = a + 0.1*10;
	printf_s("a=%f", a/10);
	getchar();
}
运行结果:



第二种是省略(直接忽略某一位的值,如下图所示)

#include <stdio.h>

void main()
{
	float a = 0;
	for (int i = 0; i < 100; i++)
		a = a + 0.1;
	printf_s("a=%.5f", a);
	getchar();
}



  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT1995

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值