用二进制如何表示浮点型数值

本文详细解析了浮点数在计算机中如何通过二进制表示,遵循IEEE754标准,介绍了符号位、指数位和尾数位的概念,并以32位和64位浮点数为例,展示了其在Java中的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:
大学期间计组没有学习好,导致怎么用浮点数表示二进制一直有点蒙,今天看到一篇不错的博文介绍这方面的,故转载记录一下。

原文:https://blog.youkuaiyun.com/ooppookid/article/details/51814335

1、用二进制如何表示浮点型数值

我们再了解二进制如何表达浮点型数值前,需要先了解用二进制如何表示整型数值:用二进制如何表示整型数值
由于计算机只认识0、1二进制,所以与表示整数一样,浮点数值最终也都会被解释为二进制机器码,与整型不同的是,所有由计算机储存的浮点类型,都是通过运算转换为十进制的,所以都是高度近似值,并不可能100%精确。具体规则如下:

  1. 遵循Ieee754标准(IEEE二进位浮点数算术标准)
  2. 首位均是符号位,1代表负,0代表正。
  3. 除去首位,用来表示浮点型的二进制要需要划分为指数位和尾数位(也称作小数位)。
不同浮点类型的指数位和尾数位占用长度不一样。

二进制转换十进制的指数偏差为:2^(指数位长度-1)-1。

这里所说的指数位、尾数位是十进制转二进制运算的关键,以32位浮点为例,它由1位符号位,8位指数位以及23位尾数位组成,例下面这个32位浮点数:

0100 0010 1101 0110 0101 0001 1100 1111

其中:指数位:100 0010 1;尾数位:101 0110 0101 0001 1100 1111。

从上面可知一下结论:

  1. 符号位为:0,即正值。
  2. 32位浮点,故指数偏差值:2^(8-1)-1 = 127。
  3. 指数位为:100 0010 1,即十进制133。
  4. 尾数位为:101 0110 0101 0001 1100 1111。

下面我们根据以上结论来运算十进制值,步骤如下:

  1. 计算指数,指数位减去指数偏差值,即133-127=6
  2. 计算小数,首先为尾数位前面补充小数点以及隐藏位1得:1.101 0110 0101 0001 1100 1111,而后右移指数6位得:1101 011.0 0101 0001 1100 1111
  3. 逐位运算,逐位求2的乘方得:
    1*(26)+1*(25)+0*(24)+1*(23)+0*(22)+1*(21)+1*(20)+小数点+0*(2-1)+0*(2-2)+1*(2-3)+0*(2-4)+1*(2-5)+0*(2-6)+0*(2-7)+0*(2-8)+1*(2-9)+1*(2-10)+1*(2-11)+0*(2-12)+0*(2-13)+1*(2-14)+1*(2-15)+1*(2-16)+1*(2-17) =107.1597824
  4. 添加符号位得:+107.1597824

由此可知,浮点类型进制转换需要耗费一定的cpu运算,而且并不精确,如果想尽量精确,需要提升浮点类型的位数,例如64位。而且在一定范围外,不同的十进制浮点数可能会转换为相同的二进制浮点数,例如:

float f3 = 423.15243f;
float f4 = 423.15244f;
System.out.println(f3 == f4);

结果为:

true

也就是说我们只能判断两个浮点数的精度差,一般使用f4 - f3 < 0.0001方式来判断两个浮点数是否相等(近似相等)。

2、Java中浮点型如何用二进制表示

在Java语言中,浮点数值分2种:float、double,均是带符号整型。

了解基本数据类型看这里:java有哪8种基本数据类型
这些类型除了长度不一致外,其他规则均按照以上规则,具体如下:

float
内存中占用8个字节,32bit。其中符号位1位,指数位8位,尾数位23位。指数偏差值:2^(8-1)-1 = 127

例如:

public class Test {

    public static void main(String[] args) throws UnsupportedEncodingException {
        float f1 = 423.1594f;
        float f2 = -423.1594f;
        int floatToIntBits1 = Float.floatToIntBits(f1);// 根据IEEE754规则,得到浮点的表示值。
        int floatToIntBits2 = Float.floatToIntBits(f2);

        System.out.println("正float===" + Integer.toBinaryString(floatToIntBits1));// 转二进制
        System.out.println("负float===" + Integer.toBinaryString(floatToIntBits2));
        System.out.println("正float===" + Integer.toHexString(floatToIntBits1));// 转十六进制
        System.out.println("负float===" + Integer.toHexString(floatToIntBits2));}
}

结果如下:
正float=1000011110100111001010001100111
负float
=11000011110100111001010001100111
正float=43d39467
负float
=c3d39467

double
内存中占用16个字节,64bit。其中符号位1位,指数位11位,尾数位52位。指数偏差值:2^(8-1)-1 = 1023

例如:

public class Test {

    public static void main(String[] args) throws UnsupportedEncodingException {
        double d1 = 423453.1597824345;
        double d2 = -423453.1597824345;
        long doubleToLongBits1 = Double.doubleToLongBits(d1);// 根据IEEE754规则,得到浮点的表示值。
        long doubleToLongBits2 = Double.doubleToLongBits(d2);

        System.out.println("正double===" + Long.toBinaryString(doubleToLongBits1));// 转二进制
        System.out.println("负double===" + Long.toBinaryString(doubleToLongBits2));
        System.out.println("正double===" + Long.toHexString(doubleToLongBits1));// 转十六进制
        System.out.println("负double===" + Long.toHexString(doubleToLongBits2));}
}

结果如下:
正double=100000100011001110110000111010010100011100111100000000110101011
负double
=1100000100011001110110000111010010100011100111100000000110101011
正double=4119d874a39e01ab
负double
=c119d874a39e01ab

在C语言中,二进制浮点型乘除计算可以使用相应的运算符来完成。 对于二进制数的乘法和除法,可以使用位运算符进行计算。二进制数的乘法可以使用左移运算符(<<)来实现。例如,将一个二进制数向左移动n位,相当于将该数乘以2的n次方。二进制数的除法可以使用右移运算符(>>)来实现。例如,将一个二进制数向右移动n位,相当于将该数除以2的n次方。这些运算符可以在C语言中直接使用,提供了方便的二进制乘除计算的方式。 对于浮点型数的乘法和除法,可以使用乘法运算符(*)和除法运算符(/)来进行计算。C语言中的浮点型数通常使用float、double或long double类型来表示。这些数值类型支持浮点数的乘法和除法操作。使用乘法运算符将两个浮点型数相乘,会得到它们的乘积。使用除法运算符将一个浮点型数除以另一个浮点型数,会得到它们的商。这些运算符在C语言中提供了方便的浮点型乘除计算的方式。 需要注意的是,在进行浮点型数的乘法和除法计算时,可能会出现精度丢失的情况。这是因为浮点数在计算机中以二进制形式存储,并且无法精确表示一些十进制小数。因此,在进行浮点型数的乘除计算时,应该注意精度问题,并尽可能使用适当的方式进行处理,以避免计算结果的错误。 总之,在C语言中,可以使用位运算符进行二进制数的乘除计算,可以使用乘法和除法运算符进行浮点型数的乘除计算。对于浮点型计算,需要注意精度问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值