16 bit float 存储_C++:float型数据存储原理及精度丢失溢出深入解析

电子计算机只能存储0和1,人类世界所能认识的任何数据都需要通过转换为二进制再进行存储。整数(int)型转换为二进制存储很好理解,那么float型数据计算机又是怎么存储的呢?常说的浮点型数据精度丢失和数据溢出又是怎么回事呢?

d5c3e47a88a2d7daf5a73ad1c640b888.png

浮点数示意图

位和字节

位:来自英文bit,音译为“比特”,表示二进制位。位是计算机内部数据储存的最小单位,11010100是一个8位二进制数。

字节:来自英文Byte,音译为“拜特”,习惯上用大写的“B”表示。
字节是计算机中数据处理的基本单位。计算机中以字节为单位存储和解释信息,规定一个字节由八个二进制位构成,即1个字节等于8个比特(1Byte=8bit)。八位二进制数最小为00000000,最大为11111111;通常1个字节可以存入一个ASCII码,2个字节可以存放一个汉字国标码。

int型数据存储

int型数据根据平台类型不同,所占用字节大小也不同,这里就按正常的4个字节来讲。整型分有符号和无符号,有符号左边最高位为符号位。

unsigned int和signed in按四个字节计算,也就是4*8=32位。int默认是signed有符号位的。所以,unsigned int表示的范围是:0~2的32次方-1。signed int表示的范围是:-2的31次方~2的31次方-1。

例如+3,转为二进制是0000 0011,但是计算机是按补码存储整型数据的,正数的补码就是其本身,但是负数的补码就不是了。

1381c3d7127df53c02d229460f3a8557.png

整形数据存储方式

float型数据存储

浮点数转二进制方法

十进制小数转换成二进制小数采用"乘2取整,按序取出"法。

整数部分按整数方式转,用短除法,小数部分按如下方式,最后再用小数点合起来;

具体做法是:用2乘十进制小数,可以得到积,将积的整数部分取出,再用2乘余下的小数部分,又得到一个积,再将积的整数部分取出,如此进行,直到积中的小数部分为零,或者达到所要求的精度为止。
然后把取出的整数部分按顺序排列起来,先取的整数作为二进制小数的高位有效位,后取的整数作为低位有效位。

例:0.734375转二进制,结果是0.101111。

0.734375 x 2 = 1.46875

0.46875 x 2 = 0.9375

0.9375 x 2 = 1.875

0.875 x 2 = 1.75

0.75 x 2 = 1.5

0.5 x 2 = 1.0

IEEE二进制浮点数算术标准

浮点数的存储方式与整型数据不同。浮点数运算有自己的标准标准,也称IEEE二进制浮点数算术标准(IEEE 754),是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算器所采用。

根据国际标准IEEE(电气和电子工程协会)规定,任何一个浮点数NUM的二进制数可以写为:
NUM = (-1) ^ S * M * 2 ^ E;//(S表示符号,E表示阶乘,M表示有效数字)

这个标准是什么意思呢?其实说白了就是二进制的科学计数法:

十进制:12345678 = 1.2345678*10^7 ;

二进制:例如十进制11.0,写成二进制就是1011.0,用IEEE标准表示就是(-1)^0 × 1.011 × 2^3 ,s=0,M=1.011,E=3;

浮点数存储

浮点数在内存中的存储按下图所示方式存储:

b549d5c7666c5446b4e49642195765b1.png

1、对于S,用来表示符号,0为正,1为负

2、对于M:规定M在存储时舍去第一个1,只存储小数点之后的数字。这样做节省了空间,以float类型为例,就可以保存23位小数信息,加上舍去的1就可以用23位来表示24个有效的信息。

3、对于E(指数)E是一个字节(8位)整数所以E的取值范围为(0~ 255),但是在计数中指数是可以为负的,所以规定在存入E时,在它原本的值上加上中间数(127),在使用时减去中间数(127),这样E的真正取值范围就成了(-127~128)。

因此对于32为单精度浮点数:在IEEE-754标准中,32位浮点数X的真值可表示为:

X = (-1)^S×(1.M)×2 ^(E-127);

精度丢失

了解了float型数据的存储原理,接下来了解一下float精度丢失的原因,以浮点数2.7为例:

首先,十进制转换成二进制。由于2.7无法用二进制精确表示,因此此处出现一次精度丢失。

2.7 => 10.10110011001…

然后,用IEEE标准表示二进制浮点数,得到s=0,M=1.010110011001…,E=1。

10.1011001… => (-1)^0 × 1.01011001… × 2^1

最后,按照IEEE标准保存数据。此时是单精度浮点数,M只能保存小数点后23位,多余的部分被丢弃了,因此此处又一次精度丢失。

ba9997d8dfa671942e1ca03f102ac577.png

精度丢失示意

溢出

既然存储有位数限制,那么溢出就很好理解了。超过最大能表示的数就是上溢,超过最小能表示的数就是下溢,只要计算出最大和最小能表示的数十多大就可以得出上下溢出的极限:

上溢极限:

1783633df186ab2c54b390a1e394545c.png

下溢极限:

5073bc08c11c7e995749c95d3adb790d.png
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
帮我看一下这个调试信息arecord -f U8 -r 8000 -c 1 --max-file-time=10 --use-strftime /mnt/disk/record/AUDIO/%y%m%d/%H%M%S.wav -vvv录音 WAVE '/mnt/disk/record/AUDIO/%y%m%d/%H%M%S.wav' : Unsigned 8 bit, Rate 8000 Hz, Mono Plug PCM: Rate conversion PCM (48000, sformat=U8 ) 换器:线性插值协议版本:10003 它的设置是:流:CAPTURE 访问:RW_INTERLEAVED 格式:U8 子格式:STD 通道:1 速率:8000 精速度:8000 (8000/1) msbits:8 buffer_size:2730 period_size :170 period_time:21333 tstamp_mode:NONE tstamp_type:MONOTONIC period_step:1 avail_min:170 period_event:0 start_threshold:1 stop_threshold:2730 silence_threshold:0 silence_size:0 boundary:178913280 从站:路由换PCM(sformat =S16_LE)换表:0 <- 00.5 + 10。5 其设置为:流:CAPTURE 访问:MMAP_INTERLEAVED 格式:U8 子格式:STD 通道:1 速率:48000 精确速率:48000 (48000/1) msbits:8 buffer_size:16384 period_size: 1024 period_time:21333 tstamp_mode:NONE tstamp_type :单调period_step:1 avail_min:1024 period_event:0 start_threshold:6 stop_threshold:16384 silence_threshold:0 silence_size:0 boundary:1073741824 Slave:Direct Snoop PCM 它的设置是:stream:CAPTURE access:MMAP_INTERLEAVED format:S16_LE subformat : STD渠道 : 2速率:48000 精确速率:48000 (48000/1) msbits:16 buffer_size:16384 period_size:1024 period_time:21333 tstamp_mode:NONE tstamp_type:单调周_STEP:1 avail_min:1024 ofer_event:0 start_thres hold:6 stop_threshold:16384 silence_thres_threshold:0 silence_size:0边界:0边界:1073741824硬件PCM卡0'usb pnp 音频设备-2 MMAP_INTERLEAVED 格式:S16_LE 子格式:STD 通道:2 速率:48000 精确速率:48000 (48000/1) msbits:16 buffer_size:16384 period_size:1024 period_time:21 333 tstamp_mode:ENABLE tstamp_type:MONOTONIC period_步骤:1 avail_min:1024 period_event:0 start_threshold :1 stop_threshold:1073741824 silence_threshold:0 silence_size:0 边界:1073741824 appl_ptr:0 hw_ptr:0 最大峰值(1个样本):0x0000000 0#0%最大峰值(1个样本):0x00000001 # 0% 最大峰值(1 个样本):0x00000001 # 0% 最大峰值(1 个样本):0x00000001 # 0% 最大峰值(1 个样本):0x00000001 # 0%最大峰值(1 个样本):0x00000001 # 0% Max peak (1 samples): 0x00000002 # 1% 这个调试信息解析0x00000002 # 1% 这个调试信息解析0x00000002 # 1% 这个调试信息解析
06-08

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值