1.1 浮動小数点数の丸め
浮動小数点数は英語で floating point number と呼ばれます。米国では、小数と整数部を区切るために「.」ドットが使われます。これが float という名前の由来です。
すでに学んだように、浮動小数点数 (float) を整数 (int) に変換すると、それは常に小数点以下が切り捨てられます。しかし、場合によっては、小数点を最も近い整数や切り上げる形で丸める必要があります。どうすれば良いでしょうか?
そのような場合、JavaScriptにはround()という組み込み関数があります。これは Math ライブラリが作られる前に生まれたので、Mathには含まれていません。ただし、切り捨てと切り上げのための関数はすべて Math ライブラリに含まれています。
Math.round() 関数
Math.round() 関数は数を最も近い整数に丸めます:
Math.round(浮動小数点数)
この関数は、渡された浮動小数点数に最も近い整数を返します。
例:
| コマンド | 結果 |
|---|---|
let x = Math.round(4.1); |
4 |
let x = Math.round(4.5); |
5 |
let x = Math.round(4.9); |
5 |
Math.ceil() 関数
Math.ceil() 関数は数を切り上げます:
| コマンド | 結果 |
|---|---|
let x = Math.ceil(4.1); |
5 |
let x = Math.ceil(4.5); |
5 |
let x = Math.ceil(4.9); |
5 |
Math.floor() 関数
Math.floor() 関数は数を切り捨てます:
| コマンド | 結果 |
|---|---|
let x = Math.floor(4.1); |
4 |
let x = Math.floor(4.5); |
4 |
let x = Math.floor(4.9); |
4 |
これらのコマンドを覚えるのが難しい場合は、簡単な英語の教訓が役立ちます:
- math — 数学
- round — 丸める
- ceiling — 天井
- floor — 床
1.2 浮動小数点数の構造
JavaScriptの number 型は、-1.7*10308 から +1.7*10308 の範囲内の値を保存できます。この巨大な範囲は、整数型とはまったく異なる構造のおかげです。 number 型の各変数には、2つの値が含まれています: 最初の値は マンティッサ、2つ目は 指数 と呼ばれます。
例えば、123456789 という数値を number 型の変数に保存するとします。この数値は 1.23456789*108 に変換され、number 型内部には 1.23456789 と 8 の2つの値が保存されます。赤は「有効桁数部分」(マンティッサ)、青は指数部分です。
このアプローチにより、極めて大きい数値や極めて小さい数値を保存できます。ただし、数値のサイズが8バイト(64ビット)に制限されており、一部のビットは 指数 を保存するために使われる(さらに、数値の符号や指数の符号も保存されます)、マンティッサの最大長は15桁に制限されます。
この説明は非常に 単純化 された浮動小数点数の構造です。詳細な情報はリンクをご覧ください。
1.3 浮動小数点数操作における精度損失
浮動小数点数を操作する際には、常にこれらが 正確ではない ことを念頭に置く必要があります。丸め誤差、10進数から2進数への変換誤差、さらには最も頻繁なケースとして大きさが異なりすぎる数値の加減算による精度損失が発生する可能性があります。
最後のケースは、プログラミング初心者にとって特に予想外かもしれません。
例えば、109 から 1/109 を引くと、再び 109 を得ます。
| 大きさが異なりすぎる数値の減算 | 説明 |
|---|---|
| 1000000000.000000000 - 0.000000001 1000000000.000000000 |
2番目の数値は小さすぎるため、有効桁部分は無視されます(灰色で表示)。赤は15桁の有効数字を示します。 |
これを見ると、プログラミングは数学とは異なることが分かりますね。
1.4 浮動小数点数比較の危険性
プログラマーは、浮動小数点数を比較する際にも注意する必要があります。これらの数値は丸め誤差が累積するため、本来等しいはずの値が等しくない場合や、その逆の場合もあります。
例:
| コマンド | 説明 |
|---|---|
let a = 1000000000.0let b = 0.000000001let c = a – b |
a の値は 1000000000.0 になります。c の値も 1000000000.0 になります( b の値が小さすぎるため)。 |
上記の例では、本来 a と c は等しくないはずですが、実際には等しくなります。
また、別の例を見てみましょう:
| コマンド | 説明 |
|---|---|
let a = 1.00000000000000001let b = 1.00000000000000002 |
a の値は 1.0 になります。b の値も 1.0 になります。 |
現実では、浮動小数点数を比較する際には、次のように行います:
2つの数値の差(絶対値)が非常に小さい値以下であれば、それらを等しいと見なします。
例:
let a = 0.00000000012;
let b = 0.000000000011;
if (Math.abs(a - b) < 0.00001) {
console.log("等しい");
} else {
console.log("等しくない");
}
GO TO FULL VERSION