IEEE754标准的c语言阐述,以及几个浮点数常量

很多年前,调研过浮点数与整数之间的双射问题:
win7 intel x64 cpu vs2013 c语言浮点数精度失真问题

最近重新学习了一下IEEE754标准,也许实际还有很多深刻问题没有被揭示。
计算机程序设计艺术,据说这本书中也有讨论。

参考:https://upimg.baike.so.com/doc/643382-681042.html
在这里插入图片描述
float32在线测试页面 :https://www.h-schmidt.net/FloatConverter/IEEE754.html
在这里插入图片描述
我用手写计算的方式,算过一遍之后,得到一个结论:
任意数值的32bit,对应的float,都可以被精确地计算,转换为一个无误差对应的字符串,且与printf %.Nf一致,只要N足够大。
eg:float FLT_TRUE_MIN == 0x00000001, 0.00000000000000000000000000000000000000000000140129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125 (149位小数)
所有其他float都是FLT_TRUE_MIN这个数的整数倍。
稍微计算几个值就明白为什么。fraction中第一个1代表0.5,第二个1是0.25,然后是0.125,0.0625,0.03125 …尾数一直可以被2整除。题外话,如果是前苏联的3进制计算机,可能就存在无限循环除不尽的问题。

但是,前面提过,float与u32的双射问题。
显然32bit最多只有4,294,967,295个值。
u32只有10位十进制数,与149位十进制小数到FLT_MAX(340282346638528859811704183484516925440.000000)是无法一一对应的。
那么中间,绝大多数的浮点数数值都没有32bit的对应值,也就是说,人工随便写的一个浮点数字符串,有99%以上的概率转换为float之后,再转换为string,是无法还原的!
但是,c基础库的printf %f和atof有一种不失真、可逆的转换实现!只是这种实现是从32bit到float string,再还原到32bit。
人为造假float值比较容易被识别,只要是不可逆的就一定是人为改过的!

个人觉得IEEE754标准的设计,c语言的实现,并不是看起来那么简单。
稍微提几个方面:硬件电路、编译器、累计误差…这些方面的坑感觉都很深。

下面是个人测试float的代码及测试结果:

#include <stdio.h>
#include <float.h>
#include <math.h>
union u32f32 {
   
   
	unsigned int u32;
	float f32;
	struct {
   
   
		unsigned int fraction : 23;
		unsigned int exp : 8;
		unsigned int sign : 1;
	};
};
static char c_u32[64] = {
   
    0 };
static char c_sign[64] = {
   
    0 };
static char c_exp[64] = {
   
    0 };
static char c_fraction[64] = {
   
    0 };
void to_binary_string_with_spaces(const unsigned int u32, const int bits, char c_temp[64]) {
   
   
	int valid_bits = bits <= 32 ? bits : 32;
	int char_index = 0;
	for (int i = valid_bits - 1; i >= 0; i--) {
   
   
		if (i % 4 == 3 && i != valid_bits - 1) {
   
   
			c_temp[char_index++] = ' ';
		}
		c_temp[char_index++] = (u32 & (1U << i)) ? '1' : '0';
	}
	c_temp[char_index] = '\0';
}
void print_float_binary(const char* p_name, const unsigned int i) {
   
   
	const union u32f32 u32_f32_obj = {
   
    .u32 = i };
	to_binary_string_with_spaces(u32_f32_obj.u32, 32, c_u32);
	to_binary_string_with_spaces(u32_f32_obj.sign, 1, c_sign);
	to_binary_string_with_spaces(u32_f32_obj.exp, 8, c_exp);
	to_binary_string_with_spaces(u32_f32_obj.fraction, 23, c_fraction)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值