### 概述
Double遵循IEEE754算數標準
Double遵循此標準中的64位浮點數表示方式。從左到右具體為:
* 第一位為符號部,0表示正,1表示負
* 2~12位為指數部,用以存放具體數值的指數
* 13~64位為尾數部
其中指數部為11位,可以表示2048個數,為-1023~+1024,因為存在正負號,會導致運算比較困難,故標準中設置了一個偏移值,將指數加上偏移值后得到編碼值存儲在指數部中,利于計算和比較。其中偏移值為2^(x-1)-1,x為指數部的位數,此處為11,故偏移值為1023.得到的編碼值范圍為0~2047(其中0(11位全是0)和2047(11位全是1)為特殊情況,下面會提到).
**規約數:**規約數是指數的編碼值(假設為Q),0<Q<2047時,所表示的數,此時尾數的個位將自動補全1.例如,十進制下的15用double存儲時,可以分以下幾步理解:
1.先將15化為2進制,為1111
2.將1111轉化為二進制下的指數形式,為1.111\* 2^3,故用double存儲時,指數為3,加上偏移值后的指數部存儲編碼值為1026,尾數部為111(小數點前的1自動補全)
3.double中的值為0100 0000 0010 1110(后面還有48個0)
但光用規約數也會產生問題,例如,只用規約數的話正數最小值為1.0\* 2^-1022,這會帶來很大麻煩,如1.2\*2^\(-1022\)-1.1\*2^\(-1022\)即0.1\*2^\(-1022\)將用Double表示時將為0,值得連續性也會在此處發生斷崖式下降(大于1.0\* 2^-1022的數,連續性為2^(-1074)),0也無法表示。故需要引入非規約數。
**非規約數**:指數部的編碼值為0,且尾數部不全為0,此時尾數部的整數位將自動補全0.
當一個數為非規約數時,指數編碼值為0,實際指數為-1022(沒錯,是-1022,不是-1023,需要加1,就是這么規定的),此時,double的連續性將處處相等,都為2^\(-1074\),并且任何兩個double的和差都能用唯一的double值表示。
當指數部編碼值為0,尾數部也為0時,double值為0,固0可以有兩種表達方式(+0和-0)
當指數部編碼為2047,尾部全為0時,表示無窮,尾部不是全為0時,表示NaN
此種設計下的double值比較十分方便,首先比較符號位,為0的一定大于為1的\(正數大于負數\),若相等,再比較指數位,因為存的編碼值都為正數,所以編碼值大的數一定大\(符號位為0的情況下,為1則結果反一下\),若還相等,最后比較尾數位,十分高效
源碼:
```
/*實現Comparable接口使Doubel對象變成可比較的對象 */
public final class Double extends Number implements Comparable<Double> {
/*在java中將 1.0 /2.0 設置為正無窮大即 Infinity*/
public static final double POSITIVE_INFINITY = 1.0 / 0.0;
/* 與上面相反 負無窮大 即 -Infinity */
public static final double NEGATIVE_INFINITY = -1.0 / 0.0;
/* 將 0.0 /0.0 設置為一個非數字的字符串*/
public static final double NaN = 0.0d / 0.0;
/* 設置最大值為1.7976931348623157e+308*/
public static final double MAX_VALUE = 0x1.fffffffffffffP+1023; // 1.7976931348623157e+308
Double.longBitsToDouble(0x0010000000000000L)}.
/* 保存 double 類型的最小正標準值的常量,最小正標準值為 2-1022。它等于十六進制的浮點字面值 0x1.0p-1022,也等于Double.longBitsToDouble(0x0010000000000000L)。 */
public static final double MIN_NORMAL = 0x1.0p-1022;
/*指數部最大值為2^1023 */
public static final int MAX_EXPONENT = 1023;
/*指數部最小值為2^-1022 */
static final int MIN_EXPONENT = -1022;
/*設置 長度為64位*/
public static final int SIZE = 64;
/* 設置為 8個字節*/
public static final int BYTES = SIZE / Byte.SIZE;
/*表示基本類型 double 的 Class 實例。 */
@SuppressWarnings("unchecked")
public static final Class<Double> TYPE = (Class<Double>) Class.getPrimitiveClass("double");
}
```
### 重點方法
* toHexString(double d)將Double的值轉換成十六進制,并返回成字符串
```
public static String toHexString(double d) {
if (!isFinite(d) ) //判斷是否超過double的最大值與最小值
return Double.toString(d);//如果超出了范圍就返回他的字符串
else {
StringBuilder answer = new StringBuilder(24);//聲明了一個StringBuilder
if (Math.copySign(1.0, d) == -1.0) //通過Math.copySign 返回的值來判斷傳入的double值是否為負數,如果是負數就是在上面的StringBuilder中添加一個負號
answer.append("-");
answer.append("0x");//十六進制以0x開頭
d = Math.abs(d);//將傳入的值進行絕對值轉換要是負數的話就變成整數,整數不變
if(d == 0.0) {
answer.append("0.0p0");//如果傳入的值為0.0直接返回0x0.0p0
} else { //傳進來的值不為0.0
boolean subnormal = (d < DoubleConsts.MIN_NORMAL);//設置一個布爾變量 判斷是否小于DoubleConsts最小值
long signifBits = (Double.doubleToLongBits(d)
& DoubleConsts.SIGNIF_BIT_MASK) |
0x1000000000000000L;
answer.append(subnormal ? "0." : "1.");
/*隔離低位十六進制的13位數字*/
String signif = Long.toHexString(signifBits).substring(3,16);
answer.append(signif.equals("0000000000000") ? // 13 zeros
"0":
signif.replaceFirst("0{1,12}$", ""));
answer.append('p');
answer.append(subnormal ?
DoubleConsts.MIN_EXPONENT:
Math.getExponent(d));
}
return answer.toString();
}
}
```
- java演變
- JDK各個版本的新特性
- JDK1.5新特性
- JDK1.6新特性
- JDK1.7新特性
- JDK1.8新特性
- JAVA基礎
- 面向對象特性
- 多態
- 方法重載
- 方法重寫
- class
- 常量
- 訪問修飾符
- 類加載路徑
- java-equals
- 局部類
- java-hashCode
- Java類初始化順序
- java-clone方法
- JAVA對象實例化的方法
- 基礎部分
- JAVA基礎特性
- JAVA關鍵字
- javabean
- static
- 日期相關
- final
- interface
- 函數式接口
- JAVA異常
- 異常屏蔽
- try-with-resource資源泄露
- JAVA引用
- WeakReference
- SoftReference
- PhantomReference
- 位運算符
- try-with-resource語法糖
- JDK冷知識
- JAVA包裝類
- JAVA基本類型與包裝類
- java.lang.Boolean
- java.lang.Integer
- java.lang.Byte
- java.lang.Short
- java.lang.Long
- java.lang.Float
- java.lang.Double
- java.lang.Character
- 日期相關
- TemporalAdjusters
- String
- 字符串常量池
- String拼接
- String編譯期優化
- StringBuilder&StringBuffer
- intern
- 注解
- java標準注解
- 內置注解
- 元注解
- 自定義注解
- 注解處理器
- JVM注解
- Java8 Annotation新特性
- 反射-Reflective
- Reflection
- Class
- Constructor
- Method
- javabean-property
- MethodHandles
- 泛型
- 類型擦除
- bridge-method
- Accessor&Mutator方法
- enum
- JAVA數組
- finalize方法
- JAR文件
- JAVA高級編程
- CORBA
- JMX
- SPI
- Java SPI使用約定
- ServiceLoader
- 實際應用
- IO
- 工具類
- JDK常用工具類
- Objects
- System
- Optional
- Throwable
- Collections
- Array
- Arrays
- System
- Unsafe
- Number
- ClassLoader
- Runtime
- Object
- Comparator
- VarHandle
- 數據結構
- 棧-Stack
- 隊列(Queue)
- Deque
- PriorityQueue
- BlockingQueue
- SynchronousQueue
- ArrayBlockingQueue
- LinkedBlockingQueue
- PriorityBlockingQueue
- ConcurrentLinkedQueue
- 列表
- 迭代器
- KV鍵值對數據類型
- HashMap
- TreeMap
- Hash沖突
- ConcurrentHashMap
- JDK1.7 ConcurrentHashMap結構
- jdk7&jdk8區別
- 集合
- Vector
- Stack
- HashSet
- TreeSet
- ArrayList
- LinkedList
- ArrayList && LinkedList相互轉換
- 線程安全的集合類
- 集合類遍歷性能
- 并發容器
- CopyOnWriteArrayList
- ConcurrentHashMap
- 同步容器
- BitMap
- BloomFilter
- SkipList
- 設計模式
- 設計模式六大原則
- 單例模式
- 代理模式
- 靜態代理
- 動態代理
- JDK動態代理
- cglib動態代理
- spring aop
- 策略模式
- SpringAOP策略模式的運用
- 生產者消費者模式
- 迭代器模式
- 函數式編程
- 方法引用
- 性能問題
- Lambda
- Lambda類型檢查
- Stream
- findFirst和findAny
- reduce
- 原始類型流特化
- 無限流
- 收集器
- 并行流
- AOP
- 靜態織入
- aspect
- aspect的定義
- AspectJ與SpringAOP
- 動態織入
- 靜態代理
- 動態代理
- JDK動態代理
- CGLib動態代理
- Spring AOP
- SpringAOP五種通知類型
- @Before
- @AfterReturning
- @AfterThrowing
- @After
- @Around
- Aspect優先級
- SpringAOP切點表達式
- within
- execution
- 嵌套調用
- 系統優化與重構
- 重疊構造器模式
- 工具類構造器優化
- 常見面試題
- new Object()到底占用幾個字節
- 訪問修飾符
- cloneable接口實現原理
- 異常分類以及處理機制
- wait和sleep的區別
- 數組在內存中如何分配
- 類加載為什么要使用雙親委派模式,有沒有什么場景是打破了這個模式
- 類的實例化順序
- 附錄
- JAVA術語
- FAQ
- 墨菲定律
- 康威定律
- 軟件設計原則
- 阿姆達爾定律
- 字節碼工具
- OSGI