> For the complete documentation index, see [llms.txt](https://lochiwei.gitbook.io/web/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://lochiwei.gitbook.io/web/js/val/prim/num/floating-point.md).

# floating-point

🚧 under construction

[JS](/web/js.md) ⟩ [value](/web/js/val.md) ⟩ [primitive](/web/js/val/prim.md) ⟩ [number](/web/js/val/prim/num.md) ⟩ floating-point

{% hint style="success" %}
the <mark style="color:yellow;">**implementation**</mark> of JavaScript’s [Number](/web/js/val/prim/num.md)：

* <mark style="color:yellow;">**based on**</mark> the “[**IEEE 754**](https://en.wikipedia.org/wiki/Double_precision_floating-point_format)” standard.
* <mark style="color:yellow;">**uses**</mark> the “<mark style="color:orange;">**double precision**</mark>” <mark style="color:yellow;">**format**</mark> (aka “<mark style="color:orange;">**64-bit**</mark>**&#x20;**<mark style="color:yellow;">**binary**</mark>”).

📗 You Don't Know JS: Types & Grammar
{% endhint %}

{% tabs %}
{% tab title="⭐️ 重點" %}
{% hint style="success" %}

* <mark style="color:red;">**all**</mark> [**numbers**](/web/js/val/prim/num.md) are <mark style="color:yellow;">**floating-point**</mark>.
* <mark style="color:red;">**all**</mark> [<mark style="color:blue;">**division**</mark>](/web/js/grammar/op/arithmetic/binary/division.md) have <mark style="color:yellow;">**floating-point**</mark> results.&#x20;
  {% endhint %}

{% hint style="info" %}
The **exponent** is an **11-bit** from 0 to 2047, in [biased form](https://en.wikipedia.org/wiki/Exponent_bias): an exponent value of **1023** represents the **actual zero**. Exponents range from **−1022** to **+1023** because exponents of **−1023** (all 0s) and **+1024** (all 1s) are reserved for **special numbers**.

📗 [Wikipedia](https://en.wikipedia.org/wiki/Double-precision_floating-point_format)
{% endhint %}
{% endtab %}

{% tab title="💈範例" %}

```javascript
// 單精度浮點數
sign
↓╭─exp──╮╭────── fraction ──────╮
001111100010000000000000000000000 = n
↑╰─8-bit╯╰─────── 23-bit ───────╯

   ⭐️ sign ↴        ↱ exp ⭐️                    ↱ fraction ⭐️
n = (-1)^sign * 2^[exp - (01111111)₂] * [1 + (.01)₂]
  =    1   *   2^(-3)   *   (1 + 1/4)
  =    1   *   0.125    *    1.25
  =    0.15625
  
// 雙精度浮點數 (double precision)(64-bit)

sign: 0 -> +, 1 -> -
exp : -1022 ~ 1023   (2^1024 ≈ 1.8 * 10^308)
frac: a₁(2)¯¹ + a₂(2)¯² + ... + a₅₂(2)¯⁵²

// ┌───────────────────────────────────────────────────────────┐
// │ n = (-1)^sign * 2^[exp - (01111111111)₂] * (1 + fraction) │
// └───────────────────────────────────────────────────────────┘

sign
↓ ╭── exp ──╮ ╭───────────────────── fraction ───────────────────╮
0 10000000000 0100000000000000000000000000000000000000000000000000
  ╰──11-bit─╯ ╰────────────────────── 52-bit ────────────────────╯
  
= (-1)⁰ * 2^[(10000000000)₂ - (01111111111)₂] * (1.01)₂
= 1 * 2 * (1.25)
= 2.5
```

{% endtab %}

{% tab title="📗 參考" %}

* [ ] JavaScript Data Structures and Algorithms (p.21, **Numbers**)
* [ ] You Don't Know JS- Types & Grammar (p.16, **Numbers**)
* [x] [從 IEEE 754 標準來看為什麼浮點誤差是無法避免的](https://medium.com/starbugs/see-why-floating-point-error-can-not-be-avoided-from-ieee-754-809720b32175)
* [ ] Wikipedia ⟩ [Double-precision floating-point format](https://en.wikipedia.org/wiki/Double-precision_floating-point_format)
* [ ] [What Every Computer Scientist Should Know About Floating-Point Arithmetic](https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html)
* [ ] [What Every Programmer Should Know About Floating-Point Arithmetic](https://floating-point-gui.de/)
  {% endtab %}

{% tab title="📘 手冊" %}

* [Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)
  {% endtab %}

{% tab title="🛠 工具" %}

* [IEEE-754 Floating Point Converter](https://www.h-schmidt.net/FloatConverter/IEEE754.html)
  {% endtab %}
  {% endtabs %}

## Floating-Point

## Number.MAX\_VALUE

```
    ┌──────────────────┐
    │ Number.MAX_VALUE │
    └──────────────────┘

      2¹⁰²³                                               2⁹⁷¹
        ↓                                                  ↓
    = 1.1111111111111111111111111111111111111111111111111111 * 2¹⁰²³
        ╰──────────────────── 52-bit ──────────────────────╯
    = 1.7976931348623157e+308
    ≈ 2¹⁰²⁴
```

## NaN

{% tabs %}
{% tab title="JS" %}

```javascript
// ⭐️ `NaN` is the ONLY ONE that doesn't equal to itself.
NaN === NaN,            // false❗️
NaN !== NaN,            // true❗️

isNaN('foo'),           // true❗️ (⭐️ DON'T use isNaN())

Number.isNaN('foo'),    // false (⭐️ use Number.isNaN() instead)
Number.isNaN(NaN),      // true

2 / 'foo',              // NaN
```

{% endtab %}

{% tab title="💾 程式" %}

* replit - [JS NaN](https://replit.com/@pegasusroe/JS-NaN#script.js)
  {% endtab %}
  {% endtabs %}

## ±Infinity & ±0

{% tabs %}
{% tab title="JS" %}

```javascript
const {log} = console;

/*
    ┌──────────────────┐
    │ Number.MAX_VALUE │
    └──────────────────┘

      2¹⁰²³                                               2⁹⁷¹
        ↓                                                  ↓
    = 1.1111111111111111111111111111111111111111111111111111 * 2¹⁰²³
        ╰──────────────────── 52-bit ──────────────────────╯
    = 1.7976931348623157e+308
    ≈ 2¹⁰²⁴
*/

// ---------- log ----------

const M = Number.MAX_VALUE;
const D = Math.pow(2, 970);     // 2⁹⁷⁰
const d = Math.pow(2, 969);     // 2⁹⁶⁹

[
    // -------- Infinity --------

     1 / 0,     //  Infinity
    -1 / 0,     // -Infinity

     Infinity === Number.POSITIVE_INFINITY, // true
    -Infinity === Number.NEGATIVE_INFINITY, // true

    3 + Infinity,           // Infinity
    3 / Infinity,           //  0
    -3 / Infinity,          // -0
    Infinity / Infinity,    // NaN

    // -------- Number.MAX_VALUE --------

    M,                      // 1.7976931348623157e+308

    // ⭐️ 只要 M 的最後一位 (2⁹⁷¹) 的一半 = 2⁹⁷⁰ 就足以讓 M 「進位」變成 Infinity
    M + D,                  // Infinity

    // ⭐️ 再小的話，則會被直接「捨棄」。
    M + d,                  // M

    // -------- Number.MAX_SAFE_INTEGER --------

    Number.MAX_SAFE_INTEGER,    // 9007199254740991 = 2⁵³ - 1
    Math.pow(2, 53) - 1,        // 9007199254740991

].forEach(x => log(x));
```

{% endtab %}

{% tab title="💾 程式" %}

* replit - [JS: ±Infinity & ±0](https://replit.com/@pegasusroe/JS-Infinity-and-0#script.js)
  {% endtab %}
  {% endtabs %}
