Java浮点数

浮点数结构

  要说清楚Java浮点数的取值范围与其精度,必须先了解浮点数的表示方法,浮点数的结构组成,之所以会有这种所谓的结构,是因为机器只认识01,你想表示小数,你要机器认识小数点这个东西,必须采用某种方法,比如,简单点的,float四个字节,前两个字节表示整数位,后两个字节表示小数位(这就是一种规则标准),这样就组成一个浮点数。而Java中浮点数采用的是IEEE 754标准。

IEEE 754

  这里就不细说什么是IEEE 754了,就直接讲具体内容,有兴趣的可以自己百度。

float

符号位(S):1bit 指数位(E):8bit 尾数位(M):23bit

一个float4字节32位,分为三部分:符号位,指数位,尾数位。
(1).符号位(S):最高位(31位)为符号位,表示整个浮点数的正负,0为正,1为负;
(2).指数位(E):23-30位共8位为指数位,这里指数的底数规定为2(取值范围:0~255)。这一部分的最终结果格式为:2E−127,即范围-127~128。另外,标准中,还规定了,当指数位8位全0或全1的时候,浮点数为非正规形式(这个时候尾数不一样了),所以指数位真正范围为:-126~127。
(3).尾数位(M):0-22位共23位为尾数位,表示小数部分的尾数,即形式为1.M或0.M,至于什么时候是1,什么时候是0,则由指数和尾数共同决定。 小数部分最高有效位是1的数被称为正规(规格化)形式。小数部分最高有效位是0的数被称为非正规(非规格化)形式,其他情况是特殊值。 最终float的值 = (−1)S∗(2E−127)∗(1.M)。具体形式如下:

符号

指数

部分

指数部分-127

尾数部分

小数部分的

最高有效位

形式

1

255

128

非0

没有

NaN

1

255

128

0

没有

负无穷

1

1~254

-126~127

任意

1

正规形式(负数)

1

0

-127

非0

0

非正规形式(负数)

1

0

-127

0

没有

负0

0

0

-127

0

没有

正0

0

0

-127

非0

0

非正规形式(正数)

0

1~254

-126~127

任意

1

正规形式(正数)

0

255

128

0

没有

正无穷

0

255

128

非0

没有

NaN

double

符号位(S):1bit 指数位(E):11bit 尾数位(M):52bit

  double这里就类似float,只是double的长度更大,所以范围就更大,但规则是一样的。double的值 = (−1)S∗(2E−1023)∗(1.M)。

取值范围

根据表1可知,float的取值范围: 
负无穷 —— −2128 ~~~ −2−149 —— 0 —— 2−149 ~~2128 —— 正无穷 
1). 上面的“——”表示中间不能取值,例如负无穷到−2128中间的值是取不到的(事实上128也是取不到的,只是接近近似值),但这并不是意味着,“~”任意值都能取到的,要注意,浮点数都是有精度的,并不能表示绝对值任意小的值。另外,Java中无穷大表示为:

Float.POSITIVE_INFINITY或Double.POSITIVE_INFINITY//表示正无穷大
Float.NEGATIVE_INFINITY或Double.NEGATIVE_INFINITY//负无穷大
//他们打印的结果:+/-Infinity
float f1 = (float)Math.pow(2,128);//指数>=128的,打印结果:Infinity
//上面要加(float)强制转换,否则编译提示出错,详细可参考前一节:Java变量数据类型
float f2 = (float)Math.pow(2,127);//1.7014118E38
System.out.println(Float.MAX_VALUE);//3.4028235E38
//其他测试,读者可自行测试
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2). -149的得来:看上面理论应该是150(指数全0,则指数值 = 0 -127,这个时候尾数取最小,2−23,则-127-23 = -150),可不知道为什么是149,我查到的资料是说,全0,全1为特殊值,不作为范围内的值,上面的float的最大最小值Float.MAX_VALUE都是接近2128)。故值 = (−1)S∗(2−126)∗(2−23) = +/-2−149

float f3 = (float) Math.pow(2,-149)//1.4E-45,小于-149,结果则为0.0
Float.MIN_VALUE //1.4E-45
  • 1
  • 2

double的取值同float: 
负无穷 —— −21024 ~~~ −2−1074 —— 0 —— 2−1074 ~~21024 —— 正无穷 
1074 =| (-1022) - (52)|

  另外,注意表格中,还有NaN,即表示非数值,例如:

System.out.println(0.0/0.0);//打印结果:NaN。注意不能是 0/0
//NaN表示计算错误,具体出现情况,可以参考表中
//Float.NaN或 Double.NaN 也能直接表示NaN,NaN与其他数计算结果均为NaN,除了
Math.pow(Float.NaN,0);//结果为1.0
//另外NaN == NaN; false
  • 1
  • 2
  • 3
  • 4
  • 5

浮点数精度

  精度是由尾数决定的,为什么?由浮点数的值计算公式可知:当指数的最终值为负,虽然这个时候浮点数的值能表示更小,但这个时候仅仅能表示0~1(或-1~0)这个数段的小数,没有实际意义。所以精度主要是看尾数的值。

float

  float的尾数:23位,其范围为:0~223,而223=8388608=106.92,所以float的精度为6~7位,能保证6位为绝对精确,7位一般也是正确的,8位就不一定了(但不是说8位就绝对不对了),注意这里的6~7位是有效小数位(大的数你先需要转换成小数的指数形式,例如:8317637.5,其有效小数位:8.3176375E6,七位),而有效位(从第一个不为0的开始数)是7~8位,是包括整数位的,像8317637.5,你不转换,则要从有效位的角度来看,有8位有效位。 
  

System.out.println((float)Math.pow(10,6.92));//注意加float强制转换
//打印结果8317637.5,float只保证7~8位有效位,其余位数舍入
  • 1
  • 2

  不理解的话,可以再这样想:23位,二进制0101……0101,尾数表示小数位,最小为0000……0001(22个0,最后一个1),即2−23=1.1920929E-7 ,这是float的最小单元(大概是0.0000001192大小,你想表示比这更小的,比如0.00000001,不可能啊),这是一个7位小数位小数,最小就是这么小,比这个更小的,计算机就无能为力了,比这个更大的,每次通过加这么一个最小单元,直到相等或接近(两个相差一个最小单元的数,它们之间的数也是不能表示的,所以有的7位也是不能精确的,因为最小不是0.0000001,而是比这个稍大)。

double

  计算方式同float,double的尾数:52位,2−52=2.220446049250313E-16,最小是16位,但最小不是1.0E-16,所以精度是15~16,能保证15,一般16位。 
  更多关于Java浮点数的,可以参考这里:基础野:细说浮点数(肥子John)

Java中float/double取值范围与精度的更多相关文章

  1. C#中float的取值范围和精度

    原文:C#中float的取值范围和精度 float类型的表现形式: 默认情况下,赋值运算符右侧的实数被视为 double. 因此,应使用后缀 f 或 F 初始化浮点型变量,如以下示例中所示: floa ...

  2. 基础学习:C#中float的取值范围和精度

    float类型的表现形式: 默认情况下,赋值运算符右侧的实数被视为 double. 因此,应使用后缀 f 或 F 初始化浮点型变量,如以下示例中所示: float x = 3.5F; 如果在以上声明中 ...

  3. java中float/double浮点数的计算失精度问题(转)

    如果我们编译运行下面这个程序会看到什么? public class Test  {    public static void main(String args[]) {                ...

  4. Java中基本数据类型byte,short,char,int,long,float,double 取值范围

    部分内容转自:java 彻底理解 byte char short int float long double 首先说byte: 这段是摘自jdk中 Byte.java中的源代码: /** * A co ...

  5. 神奇:java中float,double,int的值比较运算

    float x = 302.01f;    System.out.println(x == 302.01); //false  System.out.println(x == 302.01f); // ...

  6. java中int,float,long,double取值范围,内存泄露

    java中int,float,long,double取值范围是多少? 写道 public class TestOutOfBound { public static void main(String[] ...

  7. Java中 float、double使用注意问题

    在java中运行一下代码 System.out.println(2.00-1.10);输出的结果是:0.8999999999999999很奇怪,并不是我们想要的值0.9 再运行如下代码:System. ...

  8. Java中float和double转换的问题

    为什么double转float不会出现数据误差,而float转double却误差如此之大?   double d = 3.14; float f = (float)d; System.out.prin ...

  9. Java 中的浮点数取精度方法

    Java 中的浮点数取精度方法 一.内容 一般在Java代码中取一个double类型的浮点数的精度,四舍五入或者直接舍去等的方式,使用了4种方法,推荐使用第一种,我已经封装成工具类了. 二.代码实现 ...

随机推荐

  1. Server.MapPath()

    ./当前目录/网站主目录../上层目录~/网站虚拟目录 如果当前的网站目录为E:\wwwroot   应用程序虚拟目录为E:\wwwroot\company 浏览的页面路径为E:\wwwroot\co ...

  2. canvas孙悟空脚踩白云今年是猴年

    效果查看:http://hovertree.com/texiao/html5/30/ 使用HTML5的canvas画的孙悟空,CSS3画的白云飘飘. 刚擒住了几个妖 又降住了几个魔 魑魅魍魉怎么他就这 ...

  3. 学习和研究下unity3d的四元数 Quaternion

    学习和研究下unity3d的四元数 Quaternion 今天准备学习和研究下unity3d的四元数 Quaternion 四元数在电脑图形学中用于表示物体的旋转,在unity中由x,y,z,w 表示 ...

  4. PHP 匹配一个汉字

    使用preg_match 必须使用u flag 这个修饰符添加的额外的功能,与Perl的PCRE不兼容. Pattern和字符串均为UTF-8编码. 从PHP 4.1.0 or greater on ...

  5. cursor:pointer的意思

    cursor规则是设定网页浏览时用户鼠标指针的样式,也就是鼠标的图形形状cursor:pointer设定鼠标的形状为一只伸出食指的手,这也是绝大多数浏览器里面鼠标停留在网页链接上方时候的样式另外可以选 ...

  6. 嵌套错误Inline markup blocks (@<p>Content</p>) cannot be nested. Only one level of inline markup is allowed

    例子: @{Html.Telerik().Splitter().Name("MainSplitter") .Orientation(SplitterOrientation.Vert ...

  7. Windows下Wamp装不上Memcache扩展

    windows下wamp装不上memcache扩展2015.03.20 No Comments 1,243 views用的是WAMP集成包,PHP版本5.5.12http://windows.php. ...

  8. NOIP2012模拟试题【奶牛晒衣服】

    1.奶牛晒衣服(dry) [问题描述] 在熊大妈英明的带领下,时针和它的同伴生下了许多牛宝宝.熊大妈决定给每个宝宝都穿上可爱的婴儿装.于是,为牛宝宝洗晒衣服就成了很不爽的事情. 圣人王担负起了这个重任 ...

  9. jquery判断移动设备代码片段;pc、iphone、安卓

    $(document).ready(function () { /* 判断设备*/ var browser={ versions:function(){ var u = navigator.userA ...

  10. Convert Sorted Array to Balanced Binary Search Tree (BST)

    (http://leetcode.com/2010/11/convert-sorted-array-into-balanced.html) Given an array where elements ...