2021年8月15日 星期日

浮點數

 整數的 1/0 會出 by zero 的例外,但浮點數不會,有三種型式,「/」左右邊其中一個是 .0 就不會出錯了

1.0/0.0 = Infinity (正無限)

-1.0/0.0 = -Infinity (負無限)

0.0/0.0 = NaN (非數字)

Math.sqrt(-2) = NaN (只要是負數就會 NaN,但 0 沒關係)

其中只有 NaN 不等於自己,所以 Float 和 Double 的 isNaN 原碼如下:

public static boolean isNaN(float v) {return (v != v);}

public static boolean isNaN(double v) {return (v != v);}


isInfinite 是否是正無限或負無限 (不包括 NaN)

isFinite 只要不是正無限、負無限、NaN 其中之一就會回傳 true



IEEE 754

程式用的是 IEEE 754 的規則,維基連結

會將浮點數分成三部分

sign + exponent + fraction => 正負數+指數+小數,sign 佔一位,0是正數;1是負數

Float 32 位元為 1 + 8 + 23,指數(10進位)要加 127

Double 64位元為 1 + 11 + 52,指數(10進位)要加 1023

指數的正規化:整數只留一位,而且一定是 1,假設 10 進位是 0.5,轉成二進位是 0.1,第一個必需是 1,所以要改成 1 * 2^-1 次方

0 01111110 00000000000000000000000 中間的是 -1 + 127  = 126 的二進位


Infinity 正無限:0 + 指數全是 1 + 小數全是 0

-Infinity 負無限:1 + 指數全是 1 + 小數全是 0

NaN 非數字:指數全是 1 + 小數不是 0,java 定義為 指數全是 1 + 小數第一個是 1 後面都是 0


※驗證:

一、以 8.5 為例,轉二進制不會循環,1000.1 轉成左邊只有一位 => 1.0001 * 2^3 (二的3次方,3是指數)

32 位元 (可用 Float.floatToIntBits(8.5F) 驗證):

0 3+127 0001000...

0 10000010 0001+19個0 => 01000001000010000000000000000000 => 1091043328


64位元(可用 Double.doubleToLongBits(8.5) 驗證)

0 3+1023 00010000000...

0 10000000010 (1後8個0) 0001+48個0 => 0100000000100001000000000000000000000000000000000000000000000000 => 4620974692658839552


二、以 12.4 為例,轉二進制會循環,1100.0110 0110 0110...(0110 沒完沒了) => 1.1000110 0110 0110...*2^3

只舉例 32 位元,看懂了自己算算看 64 位元

0 3+127 1000110 0110 0110 0110....

0 10000010 1000110 0110 0110 0110 0110 => 01000001010001100110011001100110 => 1095132774


三、正負無限

32位元

0 + 8個1 + 23個0 01111111100000000000000000000000 --> 7F800000

1 + 8個1 + 23個0 11111111100000000000000000000000 --> FF800000


64位元

0 + 11個1 + 52個0 0111111111110000000000000000000000000000000000000000000000000000 --> 7FF0000000000000

1 + 11個1 + 52個0 1111111111110000000000000000000000000000000000000000000000000000 --> FFF0000000000000


四、NaN

32位元

0 + 8個1 + 頭一個是1後面都是0

01111111110000000000000000000000 --> 7FC00000


64位元

0 + 11個1 + 頭一個是1後面都是0

0111111111111000000000000000000000000000000000000000000000000000

7FF8000000000000