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.hqwc.cn/news/505031.html

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

相关文章

基于ssm疫情期间高校防控系统+vue论文

摘 要 传统信息的管理大部分依赖于管理人员的手工登记与管理&#xff0c;然而&#xff0c;随着近些年信息技术的迅猛发展&#xff0c;让许多比较老套的信息管理模式进行了更新迭代&#xff0c;学生信息因为其管理内容繁杂&#xff0c;管理数量繁多导致手工进行处理不能满足广大…

用电商API,轻松获取淘宝商品数据!

我们进入到淘宝商品数据页面&#xff0c;按F12打开开发者模式&#xff0c;对页面进行观察&#xff0c;我们发现淘宝页面是Ajax方式加载的&#xff0c;而且它的接口参数很复杂且没有固定的规律&#xff0c;但是Selenium又被淘宝反爬限制了&#xff0c;所以我们不能使用Ajax来获取…

C/C++内存管理及内存泄漏详解

目录 C/C内存分布 C语言中动态内存管理方式&#xff1a;malloc/calloc/realloc/free C内存管理方式 new/delete操作内置类型 new和delete操作自定义类型 operator new与operator delete函数 new和delete的实现原理 内置类型 自定义类型 内存泄漏 概念 内存泄漏分类 ⭐…

探索数据宇宙:深入解析大数据分析与管理技术

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua&#xff0c;在这里我会分享我的知识和经验。&#x…

多线程(进阶四:线程安全的集合类)

目录 一、多线程环境使用ArrayList 二、多线程环境使用队列 三、多线程环境使用哈希表 1、HashMap 2、Hashtable 3、ConcurrentHashMap (1)缩小了锁的粒度 (2)充分使用了CAS原子操作&#xff0c;减少一些加锁 (3)针对扩容操作的一些优化&#xff08;化整为零&#xff…

【C初阶】预处理

前言&#xff1a;在本文中&#xff0c;我将系统的整理一下C语言关于预处理部分的语法&#xff0c;便于整理与回归。 1.预定义符号 在C语言中&#xff0c;C标准提供里一些C预定义符号&#xff0c;在预处理期间完成&#xff0c;可以直接使用。 有如下几个符号&#xff1a; 2.#…

MQL5学习之RSI指标编写

研究MT5时发现MQL5这个指标编写功能很强大&#xff0c;应该是碾压国内所有的指标系统&#xff0c;不过这个东西相对复杂很多&#xff0c;比通达信公式不知复杂几许&#xff0c;看起来和C语法接近&#xff0c;倒是比较适合自己。试着玩一下&#xff0c;发现还是有点难度的。索性…

Snagit 2024:让你的屏幕活动瞬间变得生动有力 mac/win版

Snagit 2024 屏幕录制与截图软件是一款功能强大的工具&#xff0c;专为现代用户设计&#xff0c;以满足他们在工作、学习和娱乐中对屏幕内容捕捉和分享的需求。这款软件结合了屏幕录制和截图功能&#xff0c;为用户提供了一种高效、便捷的方式来捕捉屏幕上的精彩瞬间。 Snagit…

相关知识1111

一、 店铺编号和相关负责人 1、天猫兄弟、锦格 京东凡越 福林哥 如萍姐 2、京东锦格 天猫凡越 林森 雷佳华 3、天猫从简 京东从简 孔哥 4、抖音锦格 拼多多凡越 鸿哥 不知道哪个店铺编号&#xff1a;0 二、天猫京东聊天界面快捷搜索商品 1、 天猫只能根据标题搜索 2、京东是…

洛谷P1509找啊找啊找GF

题解&#xff1a;这题我们需要考虑两个因素 &#xff0c;既要有钱&#xff0c;也需要有人品&#xff0c;但是呢&#xff0c;还想花最少得时间泡到最多的女生&#xff0c;那么这题我们就要用到以往的二维dp数组&#xff0c;但是真的是二维的吗&#xff1f;不&#xff0c;因为要考…

2024国际元宇宙博览会:阿里元境以元宇宙数字内容助力文旅数字化发展

2月26日&#xff0c;MES2024国际元宇宙博览会在深圳会展中心正式开幕&#xff0c;大会以“向3D出发&#xff0c;元宇宙来袭&#xff0c;电竞娱乐正当时”为主题&#xff0c;聚焦元宇宙产业链&#xff0c;以“汇聚企业创新&#xff0c;助力产业重构&#xff0c;推动行业发展”为…

C++ //练习 10.19 用stable_partition重写前一题的程序,与stable_sort类似,在划分后的序列中维持原有元素的顺序。

C Primer&#xff08;第5版&#xff09; 练习 10.19 练习 10.19 用stable_partition重写前一题的程序&#xff0c;与stable_sort类似&#xff0c;在划分后的序列中维持原有元素的顺序。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim …