# ECMAScriptの浮動小数点数の丸め関数
[ECMAScriptの浮動小数点数の丸め仕様がスゴい - hnwの日記](https://hnw.hatenablog.com/entry/2019/02/26/114349)
[20.1.3.3Number.prototype.toFixed](https://262.ecma-international.org/8.0/#sec-number.prototype.tofixed)
The following steps are performed:
1. Let $x$ be ? [thisNumberValue](https://262.ecma-international.org/8.0/#sec-thisnumbervalue)(**this** value).
2. Let $f$ be ? [ToInteger](https://262.ecma-international.org/8.0/#sec-tointeger)($fractionDigits$). (If $fractionDigits$ is **undefined**, this step produces the value 0.)
3. If $f$ < 0 or $x$ > 20, throw a **RangeError** exception. However, an implementation is permitted to extend the behaviour of `toFixed` for values of f less than 0 or greater than 20. In this case `toFixed` would not necessarily throw **RangeError** for such values.
4. If $x$ is **NaN**, return the String `"NaN"`.
5. Let $s$ be the empty String.
6. If $x$ < 0, then
1. Let $s$ be `"-"`.
2. Let $x$ be -$x$.
7. If $x$ ≥ $10^{21}$, then
1. Let $m$ be ! [ToString](https://262.ecma-international.org/8.0/#sec-tostring)($x$).
8. Else $x$ < 1021,
1. Let $n$ be an integer for which the exact mathematical value of $n$ ÷ $10^f$ - $x$ is as close to zero as possible. If there are two such $n$, pick the larger $n$.
2. If $n$ = 0, let $m$ be the String `"0"`. Otherwise, let m be the String consisting of the digits of the decimal representation of n (in order, with no leading zeroes).
3. If $f$ ≠ 0, then
1. Let $k$ be the number of elements in $m$.
2. If $k$ ≤ $f$, then
1. Let $z$ be the String consisting of $f$+1-$k$ occurrences of the code unit 0x0030 (DIGIT ZERO).
2. Let $m$ be the concatenation of Strings $z$ and $m$.
3. Let $k$ be $f$ + 1.
3. Let $a$ be the first $k$-$f$ elements of $m$, and let $b$ be the remaining $f$ elements of $m$.
4. Let $m$ be the concatenation of the three Strings $a$, `"."`, and $b$.
9. Return the concatenation of the Strings $s$ and $m$.
- ポイント1:返り値が文字列型である
- この関数は丸めの結果を文字列型で返します。これは明確な意図と知見が感じられる仕様だと思います。
- `(1.23456).toFixed(4)` の結果は10進表記で1.2346になりますが、コンピュータ上の浮動小数点数は2進数なのでピッタリ表現できません。
- ポイント2:最近接の値を「数学的に正確な値」で判断している
- 与えられた浮動小数点数を上下どちらに丸めるか計算する際に「the exact mathematical value」で比較しなさい、と書いてあります。
- 丸め方向を決定する際に浮動小数点数の加減算や比較演算をしてはいけない、と言っているのです。
- ポイント3:仕様の大半が擬似コードで表現されている
_そもそも浮動小数点数の性質に詳しければ内部的には100倍や1000倍した整数で処理し、表示のときだけ小数点数表示するなどしてこの手の罠を踏むことはなくなるはずです。_
**ブラウザでの挙動**
[Number.prototype.toFixed()](https://hnw.jp/bugs/tofixed.html)