单精度浮点数(IEEE754)

本文详细解析了单精度浮点数在计算机内存中的存储格式,并通过实例展示了如何将32位串转换为十进制数,以及如何将十进制数转换为二进制单精度浮点数的过程。

 

单精度浮点数占据4个字节,4个字节的分配如下:

(a)第一位为符号位,0表示正,1表示负;

(b)第2~9位为阶码,采用移码表示;

(c)第10~32位为尾数,采用原码表示。

 

(1)给定32位串,如何转换成十进制数

假设内存中存在32位串:CD CC 08 41。因为INTEL CPU采用little endian存储方式,所以其真实的值为:41 08 CC CD。将其写成二进制形式:

 

0  10000010  00010001100110011001101

该浮点数为正数,阶码为10000010,尾数部分为00010001100110011001101。因为在IEEE754中,单精度浮点数有规格化处理,所以其真正尾数部分为1.00010001100110011001101,其中‘.’为小数点。

移码的10000010表示3(127+3),所以尾数部分的小数点必须向右移动3位才能得到真实的数据。真实数据为:

1000.10001100110011001101,其十进制值为:

8+0.5+1/32+1/64+1/256+1/512+1/4096+1/2^13+1/2^16+1/2^17+1/2^20+1/2^21+1/2^23 ~= 8.55

 

(2)如何将十进制数转换成二进制的单精度浮点数

 

给定数123.5,其对应的二进制原码为:1111011.1,左移六位得:(1.1110111)*2^6。根据规格化处理,所有尾数部分都转化为1.M形式,其中整数部分1可以省略,所以尾数部分为:1110111。因为左移六位,其阶码值为6,阶码的移码表示为(127+6)=133=10000101。有了尾数部分和阶码部分,我们就可以得到123.5的单精度浮点数位串:

0 10000101 11101110000000000000000

其十六进制表示为:42 F7 00 00,按照little endian存储方式,其内存值为:00 00 F7 42



欲详细了解原码、反码、补码的细节,请参阅牛人的文章:http://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html 

IEEE 754单精度浮点加法的计算方法可按以下步骤进行: ### 1. 解析浮点数 IEEE 754单精度浮点由1位符号位(S)、8位阶码(E)和23位尾(M)组成。将参与运算的两个浮点数分别解析为这三部分。例如对于浮点数,首先确定其符号(0表示正,1表示负),提取出阶码和尾部分。 ### 2. 对阶 对阶的目的是使两个浮点数的阶码相同。比较两个浮点数的阶码大小,将阶码小的浮点数的尾右移,同时阶码加1,直到两个浮点数的阶码相等。在对阶时,尾右移可能造成精度丢失,这就需要引入舍入规则来降低精度损失,常见的舍入规则有0舍1入法和恒置1法。0舍1入法是当被移除的最高值位为1,在尾的末位加1;当被移除的最高值位为0,则舍去。恒置1法是无论移除什么值,将尾的末位置1 [^2]。 ### 3. 尾相加 在对阶完成后,两个浮点数的阶码相同,此时将它们的尾按照符号位进行相加。如果两个符号相同,则直接相加;如果符号不同,则进行减法运算。 ### 4. 规格化 对相加后的尾进行规格化处理。若尾的最高位不为1,则需要进行左规或右规操作。左规是将尾左移,阶码减1;右规是将尾右移,阶码加1。右规时同样可能造成精度丢失,也需要根据舍入规则进行处理 [^2]。 ### 5. 检查溢出和下溢 检查阶码是否超出了单精度浮点所能表示的范围。如果阶码超出最大值,则发生溢出;如果阶码小于最小值,则发生下溢。 ### 6. 结果组合 将最终的符号位、阶码和尾组合成一个新的IEEE 754单精度浮点。 以计算0.75 +( - 65.25)为例,先将0.75和 - 65.25分别转换为IEEE 754单精度浮点的形式,得到符号、阶码和尾部分(0.75:符号位0,阶码0111 1110,尾10...0; - 65.25:符号位1,阶码1000 0101,尾00000101...0),然后按照上述步骤进行对阶、尾相加、规格化等操作 [^3]。 ### 代码示例 ```python import struct def float_to_ieee754(num): packed = struct.pack('>f', num) hex_str = ''.join(f'{b:02x}' for b in packed) binary_str = bin(int(hex_str, 16))[2:].zfill(32) sign = binary_str[0] exponent = binary_str[1:9] mantissa = binary_str[9:] return sign, exponent, mantissa def ieee754_to_float(sign, exponent, mantissa): binary_str = sign + exponent + mantissa hex_str = hex(int(binary_str, 2))[2:].zfill(8) packed = bytes.fromhex(hex_str) num = struct.unpack('>f', packed)[0] return num def add_ieee754(num1, num2): sign1, exponent1, mantissa1 = float_to_ieee754(num1) sign2, exponent2, mantissa2 = float_to_ieee754(num2) # 对阶 exp1 = int(exponent1, 2) exp2 = int(exponent2, 2) if exp1 > exp2: shift = exp1 - exp2 mantissa2 = '0' * shift + mantissa2[:-shift] exponent2 = exponent1 elif exp2 > exp1: shift = exp2 - exp1 mantissa1 = '0' * shift + mantissa1[:-shift] exponent1 = exponent2 # 尾相加 m1 = int('1' + mantissa1, 2) m2 = int('1' + mantissa2, 2) if sign1 == '0' and sign2 == '1': result_mantissa = m1 - m2 elif sign1 == '1' and sign2 == '0': result_mantissa = m2 - m1 else: result_mantissa = m1 + m2 # 规格化 result_sign = '0' if result_mantissa >= 0 else '1' result_mantissa = abs(result_mantissa) result_mantissa_str = bin(result_mantissa)[3:] result_exponent = exponent1 # 组合结果 return ieee754_to_float(result_sign, result_exponent, result_mantissa_str) num1 = 0.75 num2 = -65.25 result = add_ieee754(num1, num2) print(result) ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值