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+38Funion u32f32 u32_f32_epsilon_obj = { .f32 = FLT_EPSILON };//1.192092896e-07Funion u32f32 u32_f32_min_obj = { .f32 = FLT_MIN };//1.175494351e-38Funion u32f32 u32_f32_true_min_obj = { .f32 = FLT_TRUE_MIN };//1.401298464e-45Funion u32f32 u32_f32_NaN_obj = { .f32 = NAN };//nanunion 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.02585928142070770263671875printf("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

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何将字体添加到 ONLYOFFICE 桌面编辑器8.0

作者&#xff1a;VincentYoung 为你写好的文字挑选一款好看的字体然而自带的字体列表却找不到你喜欢的怎么办&#xff1f;这只需要自己手动安装一款字体即可。这里教你在不同的桌面操作系统里的多种字体安装方法。 ONLYOFFICE 桌面编辑器 ONLYOFFICE 桌面编辑器是一款免费的办…

【C语言】终の指针(前篇)

个人主页点这里~ 指针初阶点这里~ 指针初阶2.0点这里~ 指针进阶点这里~ 终の指针 一、回调函数二、qsort函数1、整形比较2、结构数据比较①结构体②-> 的使用③结构数据比较 一、回调函数 回调函数就是⼀个通过函数指针调用的函数。 把一个函数的指针作为参数传递给另一…

@ResponseStatus

目录 概述&#xff1a; 用途&#xff1a; 参数&#xff1a; 注意事项&#xff1a; 自定义异常类&#xff1a; 底层原理&#xff1a; 概述&#xff1a; 在 Spring MVC 中&#xff0c;我们有很多方法来设置 HTTP 响应的状态码其中最直接的方法&#xff1a;使用 ResponseSt…

思维题(蓝桥杯 填空题 C++)

目录 题目一&#xff1a; ​编辑 代码&#xff1a; 题目二&#xff1a; 代码&#xff1a; 题目三&#xff1a; 代码&#xff1a; 题目四&#xff1a; 代码&#xff1a; 题目五&#xff1a; 代码&#xff1a; 题目六&#xff1a; 代码七&#xff1a; 题目八&#x…

分享关于如何解决系统设计问题的逐步框架

公司广泛采用系统设计面试&#xff0c;因为在这些面试中测试的沟通和解决问题的技能与软件工程师日常工作所需的技能相似。面试官的评估基于她如何分析一个模糊的问题以及如何逐步解决问题。测试的能力还包括她如何解释这个想法&#xff0c;与他人讨论&#xff0c;以及评估和优…

外包干了2年,技术退步明显

先说一下自己的情况&#xff0c;研究生&#xff0c;19年进入广州某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试&#xf…

docker部署若依项目

目录 目录 一、搭建局域 二、redis安装 1.创建目录 2. redis.conf修改 三、MySQL安装 1. 安装 2. 设置远程连接 3. 创建数据库 四、若依后端项目搭建 1. 切换到家目录 2. 上传jar包 3. 上传Dockerfile文件 4. 构建镜像 5. 运行容器 6. 查看运行情况 7. 测试(自己…

mysql bug( InnoDB: Error number 22),表突然不能读取

mysql bug&#xff08; InnoDB: Error number 22&#xff09;&#xff0c;表突然不能读取 bug最开始的bug&#xff1a;表突然不能读取关闭mysql容器&#xff0c;再次重启失败 解决方案不重建容器的几种可能措施重建容器重建如果懒得打命令或者忘记命令可能的run bug&#xff1a…

Hololens 2应用开发系列(2)——MRTK基础知识及配置文件配置(上)

Hololens 2应用开发系列&#xff08;2&#xff09;——MRTK基础知识及配置文件配置 一、前言二、MRTK基础知识2.1 MRTK概述2.2 MRTK运行逻辑2.3 MRTK配置文件介绍2.4 MRTK服务 三、配置文件使用3.1 总配置文件3.2 相机配置3.3 其他配置 参考文献 一、前言 在前面的文章中&…

【智能家居入门1之环境信息监测】(STM32、ONENET云平台、微信小程序、HTTP协议)

作为入门本篇只实现微信小程序接收下位机上传的数据&#xff0c;之后会持续发布如下项目&#xff1a;①可以实现微信小程序控制下位机动作&#xff0c;真正意义上的智能家居&#xff1b;②将网络通讯协议换成MQTT协议再实现上述功能&#xff0c;此时的服务器也不再是ONENET&…

一文看懂:组件化设计,B端系统不再重复造轮子。

B端组件化设计是指将企业级系统的界面设计和开发分解为独立的可复用组件&#xff0c;以实现系统的模块化和灵活性。 B端组件化设计的核心思想是将界面拆分成独立的功能组件&#xff0c;每个组件负责特定的功能或业务逻辑&#xff0c;可以独立开发、测试和维护&#xff0c;同时可…

[HackMyVM]靶场 Wild

kali:192.168.56.104 主机发现 arp-scan -l # arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:d2:e0:49, IPv4: 192.168.56.104 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.56.1 0a:00:27:00:00:05 …

综合练习

Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 现有一个商店的数据库&#xff0c;记录顾客及其购物情况。根据要求完成任务 此数据库由下面 3 个表组成。 商品 product&#xff08;商品号 productid&#xff0c;商品名 p…

交友盲盒系统PHP开源的盲盒源码

源码介绍&#xff1a; 交友盲盒系统是一款基于PHP开发的开源免费盲盒系统&#xff0c;旨在为用户提供一个充满乐趣和惊喜的社交体验。该系统具有丰富的功能和灵活的扩展性&#xff0c;可以轻松地满足各种线上交友、抽奖活动等场景的需求。 安装说明&#xff1a; PHP版本&…

海外IP代理应用:亚马逊使用什么代理IP?

代理IP作为网络活动的有力工具&#xff0c;同时也是跨境电商的必备神器。亚马逊作为跨境电商的头部平台&#xff0c;吸引了大量的跨境电商玩家入驻&#xff0c;想要做好亚马逊&#xff0c;养号、测评都需要代理IP的帮助。那么应该使用什么代理IP呢&#xff1f;如何使用&#xf…

LeetCode 刷题 [C++] 第300题.最长递增子序列

题目描述 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元素而不改变其余元素的顺序。例如&#xff0c;[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。 题目…

【学习笔记】卫星基础知识

一、什么是卫星以及它如何工作&#xff1f; 通信卫星是一种人造卫星&#xff0c;通过使用转发器在源和接收器之间中继和放大无线电电信信号。卫星的工作原理是接收从地球发送的无线电信号并将无线电信号重新发送回地球。卫星使用从大型太阳能电池阵列收集的太阳能&#xff0c;…

npm ERR! code ERR_INVALID_URL报错解决

这个报错是URL错误&#xff0c;要排除两个点 npm的registry有没有搞错&#xff0c;也就是npm源有没有搞错 打开文件C:/User/<用户名>/.npmrc查看npm设置查看registry的设置有没有格式错误正确设置格式&#xff1a;registry"https://registry.npmmirror.com"或…

Spring揭秘:ApplicationContextAware应用场景及实现原理!

内容概要 ApplicationContextAware接口能够轻松感知并在Spring中获取应用上下文&#xff0c;进而访问容器中的其他Bean和资源&#xff0c;这增强了组件间的解耦&#xff0c;了代码的灵活性和可扩展性&#xff0c;是Spring框架中实现高级功能的关键接口之一。 核心概念 它能用…

双体系Java学习之关键字,标识符以及命名规范

刚开学&#xff0c;然后之前的课程暂时停在了多态&#xff0c;接下来开始跟着学校的步伐重新开始学一下&#xff0c;谢谢&#xff01;&#xff01;&#xff01; 关键字 标识符 命名规范