[Russ Cox] 浮動小数点変換の革新: より簡単に、より高速に、よりシンプルに
(research.swtch.com)要約:
- Russ Coxが提案する新しい浮動小数点変換アルゴリズムは、既存の複雑なアルゴリズム(Ryū、Dragonbox など)よりもシンプルでありながら高性能です。
- 「Unrounded Scaling」という中核プリミティブにより、2進数と10進数の間の変換を64ビット乗算1回レベルまで高速化します。
- この実装は Go 1.27(2026年8月予定)に含まれる見込みで、固定精度出力と最短幅のパース/出力の両方をサポートします。
- 既存実装と比べた性能向上
- 出力(Printing)性能: 約10〜30%向上
- パース(Parsing)性能: 約5〜15%向上
詳細要約:
1. 背景: 浮動小数点変換における慢性的な複雑さ
コンピュータの2進浮動小数点(Floating-point)を人が読める10進数に変換したり、その逆を行ったりする処理は、数十年にわたり多数のアルゴリズム(Dragon4、Grisu3、Ryū、Dragonbox など)が競い合ってきた分野です。Russ Cox は過去に「変換は簡単だが速度が問題だ」と述べていましたが、今回の投稿では 「高速な変換アルゴリズムもシンプルであり得る」 ことを証明しました。
2. 中核アイデア: Unrounded Numbers (⟨x⟩)
このアルゴリズムの基礎は unrounded 型です。これは数値の整数部分だけでなく、丸めに必要な情報(1/2ビットと、それより下位のビット群の OR 値である「sticky bit」)を含む2ビットの追加情報を保持します。
- 構造:
⟨x⟩ = ⌊4x⌋ | (4x ≠ ⌊4x⌋) - 利点: この形式を維持すると、床関数(floor)、天井関数(ceil)、あるいは浮動小数点で最も重要な「Round-to-nearest, ties-to-even」演算を非常に低コストで実行できます。
3. 高速非丸めスケーリング (Fast Unrounded Scaling)
最も重要な関数は uscale(x, e, p) です。これは の unrounded 結果を計算します。
既存アルゴリズムでは非常に大きな整数演算が必要でしたが、この方式では次のような原理により64ビット演算内で処理します。
// 概念的な実装例(実際の最適化版はさらに複雑)
func uscale(x uint64, e, p int) unrounded {
// 10^p を 2^k * 正確な分数で近似して計算
// ほとんどの場合、単一の64ビット乗算(mul64)とシフト演算に帰着
}
4. 主な成果と性能
- シンプルさ: 実装コードが非常に短く、保守しやすく、論理的な証明も可能です。
- 性能: ベンチマークの結果、現在最速とされる
Dragonbox(出力)およびEisel-Lemire(パース)アルゴリズムよりも高速な性能を示しています。 - 汎用性: 固定幅出力(Fixed-width printing)と、元の値を完全に復元できる最短幅出力(Shortest-width printing)の両方に適用できます。
5. 開発者にとっての意味
このアルゴリズムは Go 言語の標準ライブラリに統合される予定です。開発者は、内部的に小数点変換が行われるとき(例: fmt.Printf("%f", f) や strconv.ParseFloat)、より少ない CPU リソースで正確な結果を得られるようになります。また、複雑な数値解析ライブラリがなくても、unrounded の概念を通じて精密な数値制御を行うための着想も得られます。```
まだコメントはありません。