浮点数的表示形式

前提:

  1. 在计算机中数据是以二进制的方式存储
  2. 浮点数使用科学计数法的方式来表示

存储方式

浮点数的存储主要分为 3 个部分:

  1. 阶符:Sign,1 位,0 表示正,1 表示负
  2. 阶码:Exponent,表示指数大小,
  3. 尾数:Mantissa,数值部分

浮点数的值:S * M * 3^E

float:4Byte = 32bit,S 占用 1bit,E 占用 8bit,M 占用 23bit
double:8Byte = 64bit,S 占用 1bit,E 占用 11bit,M 占用 52bit

转换

举例,将 1 个 float 数据转换为 4Byte 的二进制数据存储起来:

float a = 10.25F;

                 Decimal       Binary 
整数部分:          10    ====>  1010
小数部分:         0.25   ====>  0.01  
科学计数法: 1.025 * 10^1 ====>  1010.01 = 1.01001 * 2^3

S = 0           ====> 0
E = 3           ====> 计算机使用 0111 1111 = 2^7 - 1 = 127 来表示 E = 0,所以当 E = 3 时,二进制表示为: 1000 0010 = 130
M = 1.01001     ====> 尾数为规格数,小数点前都是 1,所以直接去掉,只保留小数部分,二进制表示为:0000 1001
            S      E                  M
10.25 ====> 0 | 1000 0010 | 00000000000000000001001

      ====> 0100 0001 0000 0000 0000 0000 0000 1001

需要注意的 3 个地方:

  1. 小数部分:0.25 = 1/4,即 2 的 -2 次方,也就是二进制的 1 小数点左移 2 位,所以得到的二进制表示为 0.01。需要注意的是:不是所有的十进制小数都能转换为二进制小数,比如十进制的 0.3,所以只能取近似值,通过 2^-n(n>0,n 为整数) 来接近 0.3

  2. 规格数:基数为 2,位数最高位为 1 的数为规格数,此时能够表示的数据精度最高。通过阶码的大小来控制小数点的位置使得尾数变为规格数的过程,称为规格化。在存储时尾数只保存了小数部分。但是规格数无法表示 0,这一点需要注意

  3. 阶码是有偏移量的,以 2^7 - 1 为基准,在转化或者解析时需要加上或者减去 127

特殊值

  1. 0:以非规格化的方式存储
  2. 无限大:阶码全为 1,尾数全为 0 表示 Infinity
  3. NaN:Not a Number,不是一个可以表达的数,用阶码全为 1,尾数不等于 0 来表示

Java 中的应用

将给定的字节数组转换为对应的浮点数,JDK 中 Float 和 Double 均提供了对应的方法来处理这种情况,以 Float 为例:

public static float intBitsToFloat(int bits)
将给定的 4 个字节转换为 int 类型,然后计算 32bit 所表示的浮点数,API 中的说明:

int s = ((bits >> 31) == 0) ? 1 : -1;
int e = ((bits >> 23) & 0xff);
int m = (e == 0) ?
                (bits & 0x7fffff) << 1 :
                (bits & 0x7fffff) | 0x800000;

浮点结果等于算术表达式 s·m·2e-150 的值

对应给定的浮点数,进行四舍五入可以使用 BigDecimal.setScale()方法,可以设定保留小数的位数,以及四舍五入的方式

参考

猜你喜欢

转载自www.cnblogs.com/magexi/p/9202172.html