C语言浮点数的讨论

1. 浮点数在内存中的存储方式

浮点数在内存中的存储方式为:符号位、指数、尾数(小数)。具体如下表格:

类型符号位指数尾数(小数)
float1位(第31位)8位(第23~30位)23位(第0~22位)
double1位(第63位)11位(第52~62位)52位(第0~51位)

float和double都是浮点数类型,float占4字节内存,double占8字节内存,所以他们所能表示的数据范围和精度不一样而已。但是,它们在计算机内部的存储方式是完全一样的。另外,浮点数是没有unsigned类型的,即浮点数是没有无符号类型的。

2. 浮点数的转换

2.1 浮点数的转换有3点

  1. 将浮点数转换为二进制
  2. 用科学计数法表示二进制浮点数
  3. 计算指数偏移后的值

注意:计算指数时,要加上偏移量的,而加上的偏移量的值与类型有关。其实float偏移量加上127,而double类型偏移量的值则加上1023。

例如:我们得到了指数是6,然后偏移后的值则是:

float:127 + 6 = 133

double:1023 + 6 = 1029

2.2 10进制浮点数在内存的表示计算示例

32.25这个浮点数在内存如何表示?

  • 首先32.25的二进制表示是:100000.01 换成指数表示是:1.0000001 * (2^5)。由此可以得出:

    • 符号位:0
    • 指数:127 + 5 = 132 ,二进制表示为:10000100
    • 小数:0000001
  • 所以,内存中32.25的float表示如下

    符号位    指数位             尾数
      0    10000100    00000010000000000000000
    转换为16进制就是:0x42010000
    

如何验证我们的推算的结果是正确的呢?

我们可以设计一段代码验证,如下:

#include <stdio.h>

int main(void)
{
	float f = 32.25;
	
	unsigned int *p = (unsigned int *)&f;
 
	printf("0x%08x\n", *p);			// 编译打印后的运行结果显示是:0x42010000

	return 0;
}

我们把这段代码编译运行后,打印结果是:0x42010000,这充分说明了我们的推算结果是正确的。

3. 关于浮点数的一些思考

int类型的表示范围:-2^31 ~ 2^31 - 1

float类型的范围:-3.4 * 10^38 ~ 3.4 * 10^38

float类型和int类型它们所占用的内存都是4个字节,但是为什么float类型比int类型的表示范围大很多?

首先,它们所占据的内存都是4个字节,说明都是只有32个0和1的组合,所以它们所能表示的数字的个数肯定是一样的。但是float类型所表示的范围却大很多,那么只能说明float类型所表示的数据是不连续的。

不连续如何理解?比如1、2、3、4、5我们可以说表示的范围是1-5,而且是连续的。但是同样,1、3、5、7、9也是表示了5个数,但是表示范围却有1-9,表示范围扩大了,但是表示的个数依然只有5个。所以float类型表示的范围变大了,说明float表示的数据是不连续的。而且这个间隔是没有规律的,数据越大的时候,间隔还会越来越大。

我们可以使用如下代码验证这一结论:

#include <stdio.h>

int main(void)
{
	float f = 123456789;     
 
	printf("f = %f\n", f);   // 打印结果f = 123456792.000000

	return 0;
}

上述代码最终打印输出的是f = 123456792.000000, 而不是f = 123456789.000000。这里就可以看出,浮点数出现了跳跃的情况,即浮点数是不连续的。

4. 总结

  1. int类型与float类型都是占据4字节内存,所以都是32个0和1的组合,所以它们所能表示的数据个数是相同的;
  2. 浮点数所表示的数据是不连续的;
  3. 浮点数只是一种近似表示法,是不能用作精确数来使用的(比如条件判断 if (f == 0.1) 这种判断不要出现);
  4. 浮点数的内存表示方法更复杂,所以浮点数的运算比int类型要慢很多。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值