C语言_浮点数_IEEE 754标准_单片机_浮点数精度

2024-05-28 16:38

本文主要是介绍C语言_浮点数_IEEE 754标准_单片机_浮点数精度,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

IEEE 754标准

float的范围

float精度

float小数

读取小数存储的原始值(举例)


 

IEEE 754标准

IEEE-754 标准浮点格式

浮点格式可分为符号位s,指数位e以及尾数位f三部分。 
其中真实的指数E相对于实际的指数有一个偏移量,所以E的值应该为e-Bias,Bias(127)即为指数偏移量。这样做的好处是便于使用无符号数来代替有符号的真实指数。尾数f字段代表纯粹的小数,它的左侧即为小数点的位置。规格化数的隐藏位默认值为1,不在格式中表达。

在IEEE-754 标准下,浮点数一共分为:

  • NaN:即Not a Number。非数的指数位全部为1 同时尾数位不全为0。在此前提下,根据尾数位首位是否为1,NaN 还可以分为SNaN 和QNaN 两类。前者参与运算时将会发生异常。
  • 无穷数:指数位全部为1 同时尾数位全为0。大。
  • 规格化数:指数位不全为1 同时尾不全为0。此时浮点数的隐含位有效,其值为1。
  • 非规格化数:指数位全为0 且尾数位不全为0。此时隐含位有效值变为0。另外需要注意,以单精度时为例,真实指数e并非0-127=-127,而是-126,这样一来就与规格化下最小真实指数e=1-127=-126 达成统一,形成过渡。非规格化数隐函位表示为了0,此时表示的数据更小,提高了精度(0.1和1.1,隐含位是0的表示的更小)。
  • 0 :指数位与尾数位都全为0,根据符号位决定正负。

 

float的范围

注意:指数的范围是-126~127,不是我们认为的-127~128 ,这个是IEEE-754标准中定义的。

(1)正数最大值如下:

高地址----------------------------->低​地址

0 (1111 1110)( 111 1111 1111 1111 1111 1111)

当我们令指数位为:1111 1110 =254 (此处不能是1111 1111=255,1111 1111是NaN),则指数为254-127=127

尾数位全为1,则最大数为1.11111111111111111111111*2^127=(2-2^-23)*2^127=3.4028*10^38,正规格化数中的最大。其中1.111 1111 1111 1111 1111 1111+ 0.000 0000 0000 0000 0000 0001=2,0.000 0000 0000 0000 0000 0000=2-2^{-23}

当符号位为1时,是表示绝对值最大的负数

高地址----------------------------->低​地址

1(1111 1110)( 111 1111 1111 1111 1111 1111)

表示-3.40*10^38

所以范围是-3.40*10^38 到 3.40*10^38

(2) float最小值(除0以外的最小值)

高地址----------------------------->低​地址

0 (0000 0001)(000 0000 0000 0000 0000 0001)

当我们令指数位为:0000 0001 =1(此处不能是0000 0000=0,指数全零是非规格化数)则指数为1-127=126

为:1.0000 0000 0000 0000 0000 001*2^-126= 1.175e-038

 

float精度

float 类型的数据精度取决于尾数,首先是在不考虑指数的情况下23位尾数能表示的范围是[0, 2^23−1],实际上尾数位前面还隐含了一个"1",所以应该是一共24位数字,所能表示的范围是[0, 2^24-1](因为隐含位默认是"1",所以表示的数最小是1不是0),看到这24位能表示的最大数字为2^{24}-1,换算成10进制就是16777215,那么[0, 16777215]都是能精确表示的

16777215 这个数字可以写成1.1111111 11111111 1111111 * 2^{23},所以这个数可以精确表示,然后考虑更大的数16777216,因为正好是2的整数次幂,可以表示1.0000000 00000000 00000000 * 2^{24}所以这个数也可以精确表示,在考虑更大的数字16777217,这个数字如果写成上面的表示方法应该是 1.0000000 00000000 00000000 1 * 2^{24},但是这时你会发现,小数点后尾数位已经是24位了,23位的存储空间已经无法精确存储,这时浮点数的精度问题也就是出现了。

看到这里发现 16777216 貌似是一个边界,超过这个数的数字开始不能精确表示了,那是不是所有大于16777216的数字都不能精确表示了呢?其实不是的,比如数字 33554432 就可以就可以精确表示成1.0000000 00000000 00000000 * 2^{25},说到这里结合上面提到的float的内存表示方式,我们可以得出大于 16777216 的数字(不超上限),只要可以表示成小于24个2的n次幂相加,并且每个n之间的差值小于24就能够精确表示。换句话来说所有大于 16777216 的合理数字,都是[0, 16777215]范围内的精确数字通过乘以2^n得到的,同理所有小于1的正数,也都是 [0, 16777215] 范围内的精确数字通过乘以2^n得到的,只不过n取负数就可以了。

16777216 已经被证实是一个边界,小于这个数的整数都可以精确表示,表示成科学技术法就是1.6777216 * 10^{7},从这里可以看出一共8位有效数字,由于最高位最大为1不能保证所有情况,所以最少能保证7位有效数字是准确的,这也就是常说float类型数据的精度。

float小数


从上面的分析我们已经知道,float可表示超过16777216范围的数字是跳跃的,同时float所能表示的小数也都是跳跃的,这些小数也必须能写成2的n次幂相加才可以,比如0.5、0.25、0.125…以及这些数字的和,像5.2这样的数字使用float类型是没办法精确存储的,5.2的二进制表示为101.0011001100110011001100110011……最后的0011无限循环下去,但是float最多能存储23位尾数,那么计算机存储的5.2应该是101.001100110011001100110,也就是数字 5.19999980926513671875,计算机使用这个最接近5.2的数来表示5.2。关于小数的精度与刚才的分析是一致的,当第8位有效数字发生变化时,float可能已经无法察觉到这种变化了。

 

读取小数存储的原始值(举例)

stm32 中小数存储计算

counter+=0.001;

if(counter==0.01)//该条件永远不会成立,十进制小数转换二进制的问题导致,应该转换为大于等于或者小于等于

asda=*(vu32*)&counter;可通过该句读取counter在内存中的存储的数据;

asda=*(vu32*)&counter;取counter地址,指针类型强制转换成vu32*,然后*取内容。

0.01为0x3C23D70A,转换成2进制

0011 1100 0010 0011 1101 0111 0000 1010

符号位 0 代表正数

指数011 1100 0  为120  (120-127)=-7,小数点左移动7。(如果是130则130-127=3,表示小数点右移动三位。)

尾数01000111101011100001010  左边有一个可以理解的二进制点。此数字从浮点数的存储形式中省略。在尾数的开头加上1和二进制点可得到以下值:

1.0100 0111 1010 1110 0001 0100 左移7位为0.0000 0010 1000 1111 0101 1100 0010 1000

http://www.ab126.com/system/7348.html (带小数的二进制转换十进制计算器的网址)

转换为十进制0.00999999977648258

实际在watch窗口中观察写入0.01为0.00999999978(被四舍五入了)

参考链接:https://blog.csdn.net/albertsh/article/details/92385277

 

 

这篇关于C语言_浮点数_IEEE 754标准_单片机_浮点数精度的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
http://www.chinasem.cn/article/1011111

相关文章

Go标准库常见错误分析和解决办法

《Go标准库常见错误分析和解决办法》Go语言的标准库为开发者提供了丰富且高效的工具,涵盖了从网络编程到文件操作等各个方面,然而,标准库虽好,使用不当却可能适得其反,正所谓工欲善其事,必先利其器,本文将... 目录1. 使用了错误的time.Duration2. time.After导致的内存泄漏3. jsO

C语言中的数据类型强制转换

《C语言中的数据类型强制转换》:本文主要介绍C语言中的数据类型强制转换方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C语言数据类型强制转换自动转换强制转换类型总结C语言数据类型强制转换强制类型转换:是通过类型转换运算来实现的,主要的数据类型转换分为自动转换

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件

C语言实现两个变量值交换的三种方式

《C语言实现两个变量值交换的三种方式》两个变量值的交换是编程中最常见的问题之一,以下将介绍三种变量的交换方式,其中第一种方式是最常用也是最实用的,后两种方式一般只在特殊限制下使用,需要的朋友可以参考下... 目录1.使用临时变量(推荐)2.相加和相减的方式(值较大时可能丢失数据)3.按位异或运算1.使用临时

使用C语言实现交换整数的奇数位和偶数位

《使用C语言实现交换整数的奇数位和偶数位》在C语言中,要交换一个整数的二进制位中的奇数位和偶数位,重点需要理解位操作,当我们谈论二进制位的奇数位和偶数位时,我们是指从右到左数的位置,本文给大家介绍了使... 目录一、问题描述二、解决思路三、函数实现四、宏实现五、总结一、问题描述使用C语言代码实现:将一个整

C语言字符函数和字符串函数示例详解

《C语言字符函数和字符串函数示例详解》本文详细介绍了C语言中字符分类函数、字符转换函数及字符串操作函数的使用方法,并通过示例代码展示了如何实现这些功能,通过这些内容,读者可以深入理解并掌握C语言中的字... 目录一、字符分类函数二、字符转换函数三、strlen的使用和模拟实现3.1strlen函数3.2st

Go语言中最便捷的http请求包resty的使用详解

《Go语言中最便捷的http请求包resty的使用详解》go语言虽然自身就有net/http包,但是说实话用起来没那么好用,resty包是go语言中一个非常受欢迎的http请求处理包,下面我们一起来学... 目录安装一、一个简单的get二、带查询参数三、设置请求头、body四、设置表单数据五、处理响应六、超

C语言中的浮点数存储详解

《C语言中的浮点数存储详解》:本文主要介绍C语言中的浮点数存储详解,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、首先明确一个概念2、接下来,讲解C语言中浮点型数存储的规则2.1、可以将上述公式分为两部分来看2.2、问:十进制小数0.5该如何存储?2.3 浮点

C++ Primer 标准库vector示例详解

《C++Primer标准库vector示例详解》该文章主要介绍了C++标准库中的vector类型,包括其定义、初始化、成员函数以及常见操作,文章详细解释了如何使用vector来存储和操作对象集合,... 目录3.3标准库Vector定义和初始化vector对象通列表初始化vector对象创建指定数量的元素值

Python中如何控制小数点精度与对齐方式

《Python中如何控制小数点精度与对齐方式》在Python编程中,数据输出格式化是一个常见的需求,尤其是在涉及到小数点精度和对齐方式时,下面小编就来为大家介绍一下如何在Python中实现这些功能吧... 目录一、控制小数点精度1. 使用 round() 函数2. 使用字符串格式化二、控制对齐方式1. 使用