Java 浮点数是如何存储的?

来源:互联网 发布:java jaon添加元素 编辑:程序博客网 时间:2024/05/16 06:06

看一个面试题,   考察面试者对浮点数存储格式的理解 :

public class Float_Double {public static void main(String[] args) {float f_v1 = 20;  float f_v2 = 20.3f;  float f_v3 = 20.5f;        double d_v1 = 20;  double d_v2 = 20.3;  double d_v3 = 20.5;System.out.println((f_v1 == d_v1)?"true":"false"); System.out.println(f_v2 == d_v2?"true":"false");  System.out.println(f_v3 == d_v3?"true":"false");}}

运行结果会是怎样的呢?, 解释运行结果的原因

这里涉及到浮点数是如何存储的.

1. 如何将十进制转换成二进制浮点数呢,  先介绍一下十进制的浮点数 转换二进制的浮点数

分为两部分:

1. 先将整数部分转换为二进制,

2. 将小数部分转换为二进制, 然后将整数部分与小数部分相加。

以 20.5 转换为例,

20转换后变为  10100

0.5  要转换二进制,需要乘2, 乘完之后 取整数部分,然后用乘的结果减去整数部分, 然后 接着乘2, 最后乘完,

如果等于0, 就取前面不为0的部分. 

0.5 * 2  = 1.0 (取1)

0 * 2 = 0   (0)

所以,  转换后 0.5 = 0.1,

所以 20.5 转换二进制后, 20.5 = 10100.1(二进制)

--------------------------------

再看一个浮点数 20.3

 20 = 10100 (二进制)

0.3  * 2= 0.6  (0)

0.6  * 2 = 1.2  (1)

0.2  *  2=  0.4 (0)

0.4  * 2 = 0.8  (0)

0.8  *2 = 1.6   (1)


计算到这里, 将再出现0.6,进入循环了,所以,结果

0.3  = 0.010011001...1001

所以20.3 = 10100.010011001...1001 (二进制).

2.  如果要把十进制浮点数,存储到内存空间中,也就是4个字节中,首先要把浮点数转换成二进制的浮点数, 然后再转换成科学计数法.

这里 20.5 = 10100.1(二进制)  = 1.01001E4(十进制科学计数) = 1.01001E100(二进制科学计数)

在java中,float 类型 数,占4个字节, 存储结构如下

符号位:   1

指数位:   8

尾数位:   23,  如下图所示




                   double 类型数,  占8个字节, 存储结构如下

符号位:1

指数位:11

尾数位: 52


存储数据是一个萝卜一个坑, 首先存储符号位, 然后是 指数,最后尾数

比如20.5 = 1.010001E100(二进制)

这里使用到移位存储, 对于float 数值来说, 指数位要加上127, 即0111111(二进制)

    00000100

+  01111111

-----------------

    1000 0011

对于double 数值来说, 指数位要加上1023, 即0111 111 111(二进制)

    000 000 0100

+  011 111 1111

-----------------

    100 000 0011


所以20.5 存储的数值 是 (float):  0-10000011-01001 00000 00000 00000 000

                                            (double):0-1000000011-01001+(47个0)

                                                                                          这里尾数位需要52位

现在看到20.5 转换为float, double 的二进制数, 指数和尾数是不同的,  注意,比较指数时  float 型会-127, double型 会-1023,因此

float 型又变成了00000100

        double型又变成0000000100          ,这时候比较,因为两个指数的位数不同,一个8位,一个10位,8位的数会在前面自动补0

比较尾数时,float型数会自动在后面补0直至与double 型相同的52位


同理20.3 存储的数值 是: (float) 0-10000011-01001 10010 10011 00101 001

                                            (double)0-1000000011-01001(后面循环1001,  直至尾数为52位)


与20.5的比较相似, 20.3的float型二进制和double型二进制,符号位与指数位都相同,  但是尾数位不相同,float型到了23位之后都是0, double型一直1001循环到52位. 这就是float型与double型比较之后不相等的原因


如果要将三个比较结果  都为true, 需在d_v2加上 (float), 也就是将double强制转为float型


0 0
原创粉丝点击