JavaScriptのMath.fround():32ビット浮動小数点に丸めて保存値と比較する
Math.fround()で数値を32ビット浮動小数点の精度に丸める方法を解説。引数・戻り値、Float32Arrayとの比較、ブラウザーとNode.jsの実行手順、入力検証と精度の制約を学べます。
数値をFloat32Arrayに保存したあと、元の数値と比較すると一致しないことがあります。保存前後で、数値を表す精度が変わるためです。
Math.fround()は、数値を32ビット単精度浮動小数点で表せる値へ丸めます。この記事では、保存先の精度に合わせて比較する例を中心に、入力検証と丸めによる制約を解説します。
何のために使うのか
JavaScriptのnumberは、通常64ビットの倍精度浮動小数点で数値を表します。一方、Float32Arrayの各要素は32ビット浮動小数点です。どちらも小数を扱えますが、保持できる精度が異なります。MDNのNumber解説とFloat32Arrayの解説で、それぞれの形式を確認できます。
たとえば、入力した値が保存後も同じか確認したい場合、64ビットの入力値と32ビットへ丸められた保存値を直接比較すると、意図しない不一致が起きます。比較する入力側にもMath.fround()を適用すると、同じ保存精度で比べられます。
これは、32ビットで保持する計測値や描画用データについて、保存後の値を照合したい場面で使えます。
動作環境と対応バージョン
2026年10月17日時点で確認したMDNのMath.fround()では、主要ブラウザー間で2015年7月から広く利用可能な機能とされています。現行のChrome、Edge、Firefox、Safariで利用できます。古い組み込みブラウザーでは、使用前に機能の有無を確認してください。
Node.jsでも利用できます。本記事のコードはNode.js 22以降を対象とし、導入された最古のバージョンは扱いません。Node.jsはV8を通じてJavaScriptの言語機能を提供します。Node.jsのECMAScript対応方針も参照してください。
サンプルはDOMや外部パッケージを使わないため、ブラウザーとNode.jsの両方で同じコードを実行できます。APIの有無はtypeof Math.fround === "function"で判定できます。ただし、未対応の古い環境では、サンプルに含まれる別の構文や組み込み機能も確認が必要です。
引数と戻り値
呼び出し方はMath.fround(value)です。Mathの静的メソッドなので、インスタンスを作る必要はありません。
- 引数の
valueには、丸めたい数値を1つ渡します。 - 戻り値は、32ビット単精度の規則で丸めた数値です。
- 戻り値のJavaScript上の型は
numberのままです。 - 元の変数や配列は変更しません。
Math.fround()を呼び出しても、以後の変数や計算が自動的に32ビットになるわけではありません。必要な位置で丸めを行う関数です。
丸め方と特殊な値
通常は最も近い表現可能な値へ丸めます。ちょうど中間なら、偶数丸めの規則が使われます。大きすぎる値を与えると、結果がInfinityまたは-Infinityになる場合があります。NaNはNaN、符号付きゼロはその符号を保ちます。詳細はMDNの仕様説明にあります。
文字列などを渡すと数値への暗黙変換が行われます。変換できない文字列はNaNになり、BigIntやSymbolはTypeErrorを起こします。数値を受け取る設計なら、呼び出す前に型を検査すると入力ミスを見つけやすくなります。MDNの数値変換規則も確認してください。
コピーして動かす実例
次のコードは、保存値との比較、同じ値へ丸められる例、不正入力の処理をまとめたものです。外部ファイルやネットワーク通信は不要です。
(() => {
"use strict";
if (typeof Math.fround !== "function") {
console.log("この環境はMath.froundに対応していません");
return;
}
function toFiniteFloat32(value) {
if (typeof value !== "number" || !Number.isFinite(value)) {
throw new TypeError("有限のnumberを指定してください");
}
const rounded = Math.fround(value);
if (!Number.isFinite(rounded)) {
throw new RangeError("丸めた結果が無限大になります");
}
return rounded;
}
const input = 16777217;
const stored = new Float32Array([input]);
const normalized = toFiniteFloat32(input);
console.log(`入力: ${input}`);
console.log(`保存値: ${stored[0]}`);
console.log(`直接比較: ${stored[0] === input}`);
console.log(`丸め後比較: ${stored[0] === normalized}`);
const first = toFiniteFloat32(16777216);
const second = toFiniteFloat32(16777217);
console.log(`別の入力が一致: ${first === second}`);
for (const invalid of ["12", 2 ** 150]) {
try {
toFiniteFloat32(invalid);
} catch (error) {
console.log(`${error.name}: ${error.message}`);
}
}
})();ブラウザーでの実行方法
現行ブラウザーで開発者ツールを開き、Consoleにコード全体を貼り付けて実行します。ブラウザーが貼り付けに関する注意を表示した場合は、内容を理解したうえでブラウザーの案内に従ってください。
コードは即時実行関数の中にあるため、同じConsoleで再実行しても、サンプルの変数宣言が前回の実行と衝突しません。
Node.jsでの実行方法
Node.js 22以降を用意し、コードをUTF-8のfround-demo.jsとして保存します。ターミナルで保存先のフォルダーへ移動し、次のコマンドを実行してください。パッケージのインストールは不要です。
node --version
node fround-demo.jsファイル名をnodeに渡す実行方法は、Node.js公式のコマンドライン実行ガイドで説明されています。
期待出力と読み方
両環境で、サンプルが出力する行は次の内容になります。これは仕様から導いた期待出力であり、この記事の作成時にコードを実行した結果ではありません。
入力: 16777217
保存値: 16777216
直接比較: false
丸め後比較: true
別の入力が一致: true
TypeError: 有限のnumberを指定してください
RangeError: 丸めた結果が無限大になります16777217は64ビットのnumberでは正確に保持できますが、この付近の32ビット浮動小数点では表現可能な整数の間隔が2になります。中間に位置するため偶数丸めが働き、保存値は16777216になります。
入力側にも同じ丸めを適用した比較はtrueです。ただし、その次の行が示すとおり、異なる入力でも同じ保存値になる場合があります。
失敗例と制約
丸め後の一致を元データの一致と考える
Math.fround(a) === Math.fround(b)が示すのは、32ビットへ丸めた値の一致です。元の値が完全に同じだったことは保証しません。
サンプルの16777216と16777217のように、丸めによって区別が消えます。識別子、件数、金額など、整数の正確さが必要なデータへ一律に適用するのは避けてください。元データを残す必要があるなら、丸め前の値を別に保持します。
入力の検査だけで安全と判断する
有限のnumberでも、32ビットへ丸めた結果が無限大になることがあります。サンプルの2 ** 150がその例です。このためtoFiniteFloat32()では、変換前と変換後の両方を検査しています。
また、非常に小さい値はゼロへ丸められる場合があります。この関数はゼロへの変化を拒否しません。微小な値の消失が問題になる用途では、許容範囲や誤差の検査を追加してください。
計算全体が32ビットになると考える
Math.fround(a + b)は加算後に丸めます。各入力も先に丸めたいなら、処理の設計が変わります。単精度の計算手順を再現する用途では、どの演算の前後で丸めるかを明確にする必要があります。
本記事の関数は同期処理です。Promiseを返さず、awaitも不要です。不正入力の例外はtry...catchで入力ごとに処理し、次の入力へ進めています。
活用事例と導入の判断
実用的なのは、32ビットで保存する値について、保存後の表現が変わるかを判断する場面です。たとえば、入力した計測値を保存用バッファーの既存値と照合する処理が考えられます。
一方、実際の測定値同士が十分近いかを調べる用途では、保存精度の一致だけでは要件を満たせません。測定機器の精度や業務上の許容差に応じた比較が必要です。
導入前に「保存形式として同じ値か」と「業務上同じとみなせる値か」を整理してください。前者にはMath.fround()が役立ち、後者には別途誤差の基準が必要です。比較の目的をコメントや関数名に残すと、後から処理を変更するときにも判断しやすくなります。
公式参考資料
Googleの優先するニュース提供元にSEの部屋を追加
Googleで、いつも読みたい情報源を選べます。登録可否はGoogleの画面で確認できます。
候補にSEの部屋が表示されない場合は、まだ追加できません。