java 浮点数默认_怎么把Java的浮点数讲的清楚明白?

跟大家分享下Java的浮点数这一问题。

在此类问题中,需要注意的是float型常量需要后缀f或F,例如3.14f,double型可以后缀d,但允许省略。初学者的一个疑惑就是 为什么表达式:

0.4==0.4f

的值是false,而不是true(实际上0.4f>0.4的值是true).

希望这个小文章,能解开初学者的疑惑(没解开也不影响编程).

从数学上看精度

0.4如果表示成二进制是:

0.0110 0110 0110 0110 ... ...

也就是说,是一个无穷级数,即(因编辑器无法表示幂,我用2(-n)表示2的-n次幂)

0.4 =

0*2(-1)+1*2(-2)+1*2(-3)+0*2(-4)... ...

从数学上看,截取无穷级数的任何有限项都是0.4的近似值,这就意味着截取的项越多,精度越高。

2

IEEE 754 浮点数标准

早期的计算机是不能处理浮点数的,直到IEEE 754 标准出现后,计算机才能处理浮点数。仔细讨论IEEE 754 标准肯定超出了本小文章的范围(应该是在《计算机组成原理》这门课程里讲授。会涉及掩码,指数,尾数以及许多知识),

为了通俗理解,解开疑惑,我们首先想到一个基本的事实是,不管它是啥标准,计算机只能用0,1组成的序列表示数据,或者说计算的(硬件)存储系统和计算机计算系统处理的都是0,1组成的序列。

例如,对于:

float x = 0.4f;

x被分配4个字节,占32位,那么32位的各个位上的0,1数字是怎样的呢?

根据IEEE 754 标准就是(32位):

10011001100110011001101

根据IEEE 754 标准,对于float单精度,第 31 位(左边第1位)表示浮点数字的符号。第 30-23位(8位)表示指数(指数加完偏移量,即加偏移量127后的值)。第 22-0 位是尾数(尾数是23位)。如图上图所示意。

我们简单解释一下:

0.4的二进制是

0.0110 0110 0110 0110 0110 0110 0110 0110 ...

根据IEEE 754,首先移动小数点(向左或向右),保证整数部分只有一位非零的1(浮点的来历,对0.4就是小数点向右移动两位):

1.100110011001100110011001100110 ...

那么指数是-2(从数学计算上看,前者是后者乘以2的-2次幂得到的)

那么根据IEEE 754 ,0.4的IEEE 754标准表示是:

符号位(第31位)是 0

指数是-2+127(加偏移量127,理由不必太懂)

尾数是:10011001100110011001101

尾数(第 22-0 位是尾数,共23位)就是从

1.100110011001100110...

小数点后面取23位(事先将第24位加1,可能进位到第23位)。

对于:

double y = 0.4;

y被分配8个字节,占64位,那么64位各个位上的0,1数字是怎样的呢?

根据IEEE 754 标准就是(64位):

00111111110110011001100110011001

10011001100110011001100110011010

根据IEEE 754 标准,对于double双精度,第 63 位表示浮点数字的符号。第 62-52 位(11位)表示指数(指数加完偏移量)。第 51-0 位是尾数(尾数是52位,尾数位比float多。尾数位越多,精度越高)。

当然我们不要按着脑海里通常的想法去把上面的0,1序列转化为熟悉的十进制,而是要按着IEEE 754标准才可以,

计算机语言恰好就是根据IEEE 754标准转化成十进制给用户看的。

那么根据IEEE 754标准比较大小:

10011001100110011001101

不等于(是大于)

00111111110110011001100110011001

10011001100110011001100110011010

当计算机语言,比如Java语言,把

10011001100110011001101

转化为十进制(根据IEEE 754标准,假如保留小数点20位):

有效数字是7-8位

(从左边第一个非零数字算起),但从第9位开始不保证有效!

00111111110110011001100110011001

10011001100110011001100110011010

转化为十进制(假如保留小数点20位):

有效数字是15-16位.

请阅读代码

运行效果如下图

如果您刚学第2章,肯定不能读懂全部代码,但可以运行它,尽量理解它(就像朋友相处的道理一样)。但是,如果您学完第4章,您也就能写出这样的代码,解答自己心中的疑惑! 比如,Float类的static方法

int floatToRawIntBits(float value)

是根据 IEEE 754 标准的位布局,返回指定浮点值value的IEEE 754 标准的表示形式。

注意:Java语言在输出正浮点数的内存形式时,就不输出符号位0,如果同时指数也是正数,也省略输出指数的符号位(比如对于float,输出的往往是30-31位,对于double,输出的往往是30-31位,对于double,输出的往往是62-63位)。

public class E {

public static void main(String args[]) {

float x = -0.4f;

double y = -0.4;

int bitInt = Float.floatToIntBits(x);

(Integer.toBinaryString(bitInt));

long bitLong = Double.doubleToLongBits(y);

(Long.toBinaryString(bitLong));

("%20.20f\n",

Float.intBitsToFloat(bitInt));

("%20.20f\n",

Double.longBitsToDouble(bitLong));

}

}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值