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);
	printf("float %s == 0x%08x, binary(%s)\n", p_name, u32_f32_obj.u32, c_u32);
	printf("float %s == 0x%08x, sign(%s)*(-1) 2^exp(%s-127) fraction(1.%s)\n",
		p_name, u32_f32_obj.u32, c_sign, c_exp, c_fraction);
}
int test_float() {
	union u32f32 u32_f32_max_obj = { .f32 = FLT_MAX };//3.402823466e+38F
	union u32f32 u32_f32_epsilon_obj = { .f32 = FLT_EPSILON };//1.192092896e-07F
	union u32f32 u32_f32_min_obj = { .f32 = FLT_MIN };//1.175494351e-38F
	union u32f32 u32_f32_true_min_obj = { .f32 = FLT_TRUE_MIN };//1.401298464e-45F
	union u32f32 u32_f32_NaN_obj = { .f32 = NAN };//nan
	union u32f32 u32_f32_inf_obj = { .f32 = INFINITY };
	union u32f32 u32_f32_ne_inf_obj = { .f32 = -INFINITY };
	union u32f32 u32_f32_0_obj = { .f32 = 0 };
	union u32f32 u32_f32_ne_0_obj = { .f32 = 0,.sign = 1 };
	printf("float FLT_MAX      == 0x%08x, %f\n", u32_f32_max_obj.u32, u32_f32_max_obj.f32);
	printf("float FLT_EPSILON  == 0x%08x, %.23f\n", u32_f32_epsilon_obj.u32, u32_f32_epsilon_obj.f32);
	printf("float FLT_MIN      == 0x%08x, %.126f\n", u32_f32_min_obj.u32, u32_f32_min_obj.f32);
	printf("float FLT_TRUE_MIN == 0x%08x, %.149f\n", u32_f32_true_min_obj.u32, u32_f32_true_min_obj.f32);
	printf("float NaN          == 0x%08x, %f\n", u32_f32_NaN_obj.u32, u32_f32_NaN_obj.f32);
	printf("float INFINITY     == 0x%08x, %f\n", u32_f32_inf_obj.u32, u32_f32_inf_obj.f32);
	printf("float -INFINITY    == 0x%08x, %f\n", u32_f32_ne_inf_obj.u32, u32_f32_ne_inf_obj.f32);
	printf("float +0           == 0x%08x, %f\n", u32_f32_0_obj.u32, u32_f32_0_obj.f32);
	printf("float -0           == 0x%08x, %f\n", u32_f32_ne_0_obj.u32, u32_f32_ne_0_obj.f32);
	//
	print_float_binary("FLT_MAX     ", u32_f32_max_obj.u32);
	print_float_binary("FLT_EPSILON ", u32_f32_epsilon_obj.u32);
	print_float_binary("FLT_MIN     ", u32_f32_min_obj.u32);
	print_float_binary("FLT_TRUE_MIN", u32_f32_true_min_obj.u32);
	print_float_binary("NaN         ", u32_f32_NaN_obj.u32);
	print_float_binary("INFINITY    ", u32_f32_inf_obj.u32);
	print_float_binary("-INFINITY   ", u32_f32_ne_inf_obj.u32);
	print_float_binary("zero(+0)    ", u32_f32_0_obj.u32);
	print_float_binary("zero(-0)    ", u32_f32_ne_0_obj.u32);
	//
	union u32f32 u32_f32_obj = { .u32 = 0xBCD3D6D8 };//0xBCD3D6D8 == -0.02585928142070770263671875
	printf("float obj_test     == 0x%08x, %.60f\n", u32_f32_obj.u32, u32_f32_obj.f32);
	print_float_binary("obj_test    ", u32_f32_obj.u32);
	//
	printf("float obj_test     == 0x%08x, sign(%s1) 2^exp(%d) fraction(%.30f)\n", u32_f32_obj.u32,
		u32_f32_obj.sign ? "-" : "+",
		((int)u32_f32_obj.exp) - 127,
		1.0 * u32_f32_obj.fraction / (1 << 23) + 1);
	printf("float obj_test     == 0x%08x, sign(%d) exp(%f) fraction(%.30f)\n", u32_f32_obj.u32,
		(-1) * (int)u32_f32_obj.sign,
		(pow(2, ((int)u32_f32_obj.exp) - 127)),
		(1.0 * u32_f32_obj.fraction / (1 << 23) + 1));
	printf("float obj_test     == 0x%08x, %.30f\n", u32_f32_obj.u32,
		(-1) * (int)u32_f32_obj.sign *
		(pow(2, ((int)u32_f32_obj.exp) - 127)) *
		(1.0 * u32_f32_obj.fraction / (1 << 23) + 1));
	return 0;
}

int main(int argc, char** argv) {
	return test_float();
}
float FLT_MAX      == 0x7f7fffff, 340282346638528859811704183484516925440.000000
float FLT_EPSILON  == 0x34000000, 0.00000011920928955078125
float FLT_MIN      == 0x00800000, 0.000000000000000000000000000000000000011754943508222875079687365372222456778186655567720875215087517062784172594547271728515625
float FLT_TRUE_MIN == 0x00000001, 0.00000000000000000000000000000000000000000000140129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125
float NaN          == 0x7fc00000, nan
float INFINITY     == 0x7f800000, inf
float -INFINITY    == 0xff800000, -inf
float +0           == 0x00000000, 0.000000
float -0           == 0x80000000, -0.000000
float FLT_MAX      == 0x7f7fffff, binary(0111 1111 0111 1111 1111 1111 1111 1111)
float FLT_MAX      == 0x7f7fffff, sign(0)*(-1) 2^exp(1111 1110-127) fraction(1.111 1111 1111 1111 1111 1111)
float FLT_EPSILON  == 0x34000000, binary(0011 0100 0000 0000 0000 0000 0000 0000)
float FLT_EPSILON  == 0x34000000, sign(0)*(-1) 2^exp(0110 1000-127) fraction(1.000 0000 0000 0000 0000 0000)
float FLT_MIN      == 0x00800000, binary(0000 0000 1000 0000 0000 0000 0000 0000)
float FLT_MIN      == 0x00800000, sign(0)*(-1) 2^exp(0000 0001-127) fraction(1.000 0000 0000 0000 0000 0000)
float FLT_TRUE_MIN == 0x00000001, binary(0000 0000 0000 0000 0000 0000 0000 0001)
float FLT_TRUE_MIN == 0x00000001, sign(0)*(-1) 2^exp(0000 0000-127) fraction(1.000 0000 0000 0000 0000 0001)
float NaN          == 0x7fc00000, binary(0111 1111 1100 0000 0000 0000 0000 0000)
float NaN          == 0x7fc00000, sign(0)*(-1) 2^exp(1111 1111-127) fraction(1.100 0000 0000 0000 0000 0000)
float INFINITY     == 0x7f800000, binary(0111 1111 1000 0000 0000 0000 0000 0000)
float INFINITY     == 0x7f800000, sign(0)*(-1) 2^exp(1111 1111-127) fraction(1.000 0000 0000 0000 0000 0000)
float -INFINITY    == 0xff800000, binary(1111 1111 1000 0000 0000 0000 0000 0000)
float -INFINITY    == 0xff800000, sign(1)*(-1) 2^exp(1111 1111-127) fraction(1.000 0000 0000 0000 0000 0000)
float zero(+0)     == 0x00000000, binary(0000 0000 0000 0000 0000 0000 0000 0000)
float zero(+0)     == 0x00000000, sign(0)*(-1) 2^exp(0000 0000-127) fraction(1.000 0000 0000 0000 0000 0000)
float zero(-0)     == 0x80000000, binary(1000 0000 0000 0000 0000 0000 0000 0000)
float zero(-0)     == 0x80000000, sign(1)*(-1) 2^exp(0000 0000-127) fraction(1.000 0000 0000 0000 0000 0000)
float obj_test     == 0xbcd3d6d8, -0.025859281420707702636718750000000000000000000000000000000000
float obj_test     == 0xbcd3d6d8, binary(1011 1100 1101 0011 1101 0110 1101 1000)
float obj_test     == 0xbcd3d6d8, sign(1)*(-1) 2^exp(0111 1001-127) fraction(1.101 0011 1101 0110 1101 1000)
float obj_test     == 0xbcd3d6d8, sign(-1) 2^exp(-6) fraction(1.654994010925292968750000000000)
float obj_test     == 0xbcd3d6d8, sign(-1) exp(0.015625) fraction(1.654994010925292968750000000000)
float obj_test     == 0xbcd3d6d8, -0.025859281420707702636718750000

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/423854.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

双周回顾#007 - 前端与后端

前端的问题不是难&#xff0c;而是它面对最终用户。只要用户的喜好和口味发生变化&#xff0c;前端就必须跟上。 这导致前端不得不快速变化&#xff0c;因为用户的口味正在越来越快地改变。 后端不需要面对最终用户&#xff0c;需要解决的都是一些经典的计算机科学问题&#…

8、Redis-Jedis、Lettuce和一个Demo

目录 一、Jedis 二、Lettuce 三、一个Demo Java集成Redis主要有3个方案&#xff1a;Jedis、Lettuce和Redisson。 其中&#xff0c;Jedis、Lettuce侧重于单例Redis&#xff0c;而Redisson侧重于分布式服务。 项目资源在文末 一、Jedis 1、创建SpringBoot项目 2、引入依赖 …

114.龙芯2k1000-pmon(13)- 串口如何用

本文是讲原理图的部分&#xff0c;跟pmon的关系不大&#xff01;&#xff01; 参考手册&#xff1a;《龙芯2K1000处理器用户手册.pdf》 刚刚看数据手册&#xff0c;让我是有点惊讶&#xff0c;但是也让我迷惑。&#xff08;一个串口复用为4个是啥意思&#xff1f;&#xff09;…

MYSQL的优化学习,从原理到索引,在到事务和锁机制,最后的主从复制、读写分离和分库分表

mysql的优化学习 为什么选择Mysql不选择其他的数据库&#xff1f;还有哪些&#xff0c;有什么区别&#xff1f; Mysql&#xff1a;开源免费版本可用&#xff0c;适用于中小型应用 Oracle&#xff1a;适用于大型企业级应用&#xff0c;复杂的业务场景和大量数据的处理&#xf…

ctf_show笔记篇(web入门---命令执行)

目录 命令执行 29&#xff1a;有很多种方法可以使用内联法例如system(cat ls)或者像它提示的一样echo nl fl""ag.php 30&#xff1a;这里与29题原理相同只不过多禁用了一个system和php####请通过29题举一反三 31&#xff1a;这一题有多种解法看自身理解&#xff0…

关于阿里云oss的冗余存储类型问题

不得不说一个问题&#xff0c;阿里云服务方便我们的同时 &#xff0c;他们的文档写的是真的差劲。 东一块&#xff0c;西一块的。非常不好系统的阅读&#xff0c;文档结构比较散。 关于阿里云oss的冗余存储类型问题&#xff0c;这里说一下&#xff0c;简直是个坑。 首页阿里…

基于springboot+vue的在线考试与学习交流平台

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

【C语言】熟悉文件基础知识

欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 文件 为了数据持久化保存&#xff0c;使用文件&#xff0c;否则数据存储在内存中&#xff0c;程序退出&#xff0c;内存回收&#xff0c;数据就会丢失。 程序设计中&…

【UEFI实战】BIOS中的openssl

BIOS中的openssl openssl是一个密码库或者密码工具&#xff0c;在密码学基础_hex string is too short, padding with zero bytes t-CSDN博客介绍了基本的密码学概念已经openssl工具的使用&#xff0c;而这里将介绍BIOS下如何使用openssl。 在开源的BIOS代码库EDK中包含一个C…

【接口测试】常见HTTP面试题

目录 HTTP GET 和 POST 的区别 GET 和 POST 方法都是安全和幂等的吗 接口幂等实现方式 说说 post 请求的几种参数格式是什么样的&#xff1f; HTTP特性 HTTP&#xff08;1.1&#xff09; 的优点有哪些&#xff1f; HTTP&#xff08;1.1&#xff09; 的缺点有哪些&#x…

车灯修复UV胶的优缺点有哪些?

车灯修复UV胶的优点如下&#xff1a; 优点&#xff1a; 快速固化&#xff1a;通过紫外光照射&#xff0c;UV胶可以在5-15秒内迅速固化&#xff0c;提高了修复效率。高度透明&#xff1a;固化后透光率高&#xff0c;几乎与原始车灯材料无法区分&#xff0c;修复后车灯外观更加…

web漏洞与规避

文章目录 一、XSS 跨站脚本攻击1.1 XSS攻击的主要类型反射型XSS存储型XSSDOM型XSS 1.2 前端开发如何应对XSS 二、CSRF 跨站请求伪造2.1 CSRF例子2.2 前端开发如何应对CSRF 三、SQL 注入3.1 前端如何防御SQL注入 四、前端如何使用CSP 一、XSS 跨站脚本攻击 攻击者通过在受害者的…

基于springboot+vue的装饰工程管理系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

重学Springboot3-@ConditionalOnXxx条件注解

重学Springboot3-ConditionalOnXxx条件注解 引言常见的条件注解常见的条件注解示例扩展条件注解1. ConditionalOnJndi2. ConditionalOnJava3. ConditionalOnCloudPlatform4. ConditionalOnEnabledResourceChain5. 自定义条件注解 总结 引言 Spring Boot 提供了一组强大的条件注…

AutoEncoder和 Denoising AutoEncoder学习笔记

参考&#xff1a; 【1】 https://lilianweng.github.io/posts/2018-08-12-vae/ 写在前面&#xff1a; 只是直觉上的认识&#xff0c;并没有数学推导。后面会写一篇&#xff08;抄&#xff09;大一统文章&#xff08;概率角度理解为什么AE要选择MSE Loss&#xff09; TOC 1 Au…

Python解释器及PyCharm安装教程

PyCharm官方下载地址☞https://www.jetbrains.com/pycharm/download/?sectionwindows Python解释器官方下载地址☞ https://www.python.org/downloads/windows/

实践航拍小目标检测,基于YOLOv8全系列【n/s/m/l/x】参数模型开发构建无人机航拍场景下的小目标检测识别分析系统

关于无人机相关的场景在我们之前的博文也有一些比较早期的实践&#xff0c;感兴趣的话可以自行移步阅读即可&#xff1a; 《deepLabV3Plus实现无人机航拍目标分割识别系统》 《基于目标检测的无人机航拍场景下小目标检测实践》 《助力环保河道水质监测&#xff0c;基于yolov…

【C++】十大排序算法之 冒泡排序 选择排序

本次介绍内容参考自&#xff1a;十大经典排序算法&#xff08;C实现&#xff09; - fengMisaka - 博客园 (cnblogs.com) 排序算法是《数据结构与算法》中最基本的算法之一。 十种常见排序算法可以分为两大类&#xff1a; 比较类排序&#xff1a;通过比较来决定元素间的相对次序…

Golang 调度器 GPM模型

Golang 调度器 GPM模型 1 多进程/线程时代有了调度器需求 在多进程/多线程的操作系统中&#xff0c;就解决了阻塞的问题&#xff0c;因为一个进程阻塞cpu可以立刻切换到其他进程中去执行&#xff0c;而且调度cpu的算法可以保证在运行的进程都可以被分配到cpu的运行时间片。这…

腾讯云幻兽帕鲁服务器使用Linux和Windows操作系统,对用户的技术要求有何不同?

腾讯云幻兽帕鲁服务器使用Linux和Windows操作系统对用户的技术要求有何不同&#xff1f; 首先&#xff0c;从操作界面的角度来看&#xff0c;Windows操作系统相对简单易操作&#xff0c;适合那些偏好使用图形化界面操作的用户。而Linux操作系统则需要通过命令行完成&#xff0…