[インデックス 1256] ファイルの概要
このコミットは、Go言語の標準ライブラリの一部であるsrc/lib/strconv/ftoa_test.go
ファイルに対する変更です。このファイルは、浮動小数点数を文字列に変換するftoa
(float-to-ASCII)関数のテストケースを含んでいます。
コミット
commit 548609654311809b904f2b5a0926f3b38b45b7b4
Author: Russ Cox <rsc@golang.org>
Date: Mon Dec 1 16:03:09 2008 -0800
be more precise in ftoa_test.
R=ken
OCL=20173
CL=20173
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/548609654311809b904f2b5a0926f3b38b45b7b4
元コミット内容
このコミットの目的は、ftoa_test.go
における浮動小数点数のテストケースの精度を向上させることです。具体的には、1e23 - 8.5e6
と1e23 + 8.5e6
という浮動小数点リテラルを、float64
型で正確に表現される定数Below1e23
とAbove1e23
に置き換えることで、テストの信頼性と再現性を高めています。
変更の背景
浮動小数点数の計算は、その性質上、常に厳密な精度を保証するわけではありません。特に、float64
(倍精度浮動小数点数)のようなバイナリ浮動小数点形式では、多くの十進数が正確に表現できないため、計算結果に微細な誤差が生じることがあります。
このコミットが行われた背景には、ftoa_test.go
内の既存のテストケースが、1e23 - 8.5e6
や1e23 + 8.5e6
といった浮動小数点リテラルを使用していたことが挙げられます。これらのリテラルは、ソースコード上では特定の十進数として記述されていますが、float64
型に変換される際に、最も近いバイナリ表現に丸められます。この丸め処理によって、意図しない値がテストに使用され、テスト結果が不安定になったり、特定の環境やコンパイラ設定によって異なる結果を生じたりする可能性がありました。
Russ Cox氏によるこの変更は、このような浮動小数点数の丸め誤差に起因するテストの不安定性を解消し、ftoa
関数のテストが常に期待通りの正確な浮動小数点値に対して行われるようにすることを目的としています。これにより、ftoa
関数の実装が、浮動小数点数の正確な文字列変換を保証しているかをより厳密に検証できるようになります。
前提知識の解説
浮動小数点数 (Floating-Point Numbers)
コンピュータにおける浮動小数点数は、実数を近似的に表現するための形式です。IEEE 754標準が広く採用されており、Go言語のfloat64
型もこの標準に準拠しています。浮動小数点数は通常、符号部、指数部、仮数部(または有効数字部)の3つの部分で構成されます。
- 符号部: 数値が正か負かを示します。
- 指数部: 小数点の位置を示し、数値の大きさを決定します。
- 仮数部: 数値の有効数字を示します。
float64
は倍精度浮動小数点数であり、64ビット(8バイト)を使用して数値を表現します。これにより、約15〜17桁の十進精度と、非常に広い範囲の数値を表現できますが、すべての実数を正確に表現できるわけではありません。特に、十進数で有限小数であっても、二進数では無限小数になる場合(例: 0.1)は、最も近い二進数で近似されるため、丸め誤差が生じます。
浮動小数点数の丸め誤差 (Rounding Errors)
浮動小数点数の計算では、表現可能な桁数や範囲の制約により、正確な値が表現できない場合に丸め処理が行われます。この丸めによって生じる誤差を丸め誤差と呼びます。例えば、1/3
は十進数では0.333...
と無限に続きますが、有限の桁数で表現する際にはどこかで打ち切られるため、誤差が生じます。同様に、二進数で表現できない十進数も丸められます。
このコミットで問題となっているのは、1e23 - 8.5e6
や1e23 + 8.5e6
といった計算結果が、float64
のバイナリ表現において、ソースコードに記述された十進数と完全に一致しない可能性がある点です。これらの計算結果は、最も近いfloat64
の表現可能な値に丸められます。
ftoa
関数 (Float-to-ASCII)
ftoa
関数は、浮動小数点数を文字列形式に変換する役割を担います。この変換は、科学技術計算の結果を人間が読める形式で表示したり、データをファイルに保存したりする際に不可欠です。ftoa
関数は、変換の際に、指数表記(e
形式)、固定小数点表記(f
形式)、またはその両方を組み合わせた一般表記(g
形式)など、様々なフォーマットオプションを提供します。これらのフォーマットは、数値の大きさや精度に応じて適切な表示形式を選択するために使用されます。
ftoa_test.go
は、このftoa
関数が、様々な浮動小数点数(正の数、負の数、ゼロ、無限大、非数(NaN)、そして非常に大きい数や小さい数)に対して、期待される文字列を正確に生成するかどうかを検証するための単体テストファイルです。
技術的詳細
このコミットの核心は、浮動小数点リテラルの代わりに、float64
型で正確に表現される定数を使用することで、テストの決定論的(deterministic)な性質を保証することにあります。
元のコードでは、1e23 - 8.5e6
という式が使用されていました。
1e23
は10^23
、8.5e6
は8.5 * 10^6
です。
この計算結果は99999999999999991500000
となります。
しかし、この十進数がfloat64
型で正確に表現できるとは限りません。float64
の内部表現では、この値に最も近い表現可能な値に丸められます。
同様に、1e23 + 8.5e6
という式も使用されていました。
この計算結果は100000000000000008500000
となります。
これもまた、float64
型で正確に表現できるとは限りません。
このコミットでは、これらの計算結果がfloat64
型で実際にどのように表現されるかを特定し、その正確なバイナリ表現に対応する十進数を定数として定義しています。
Below1e23 = 99999999999999974834176
Above1e23 = 100000000000000008388608
これらの定数は、それぞれ1e23 - 8.5e6
と1e23 + 8.5e6
をfloat64
として計算した際に、実際にメモリに格納される正確な値(最も近い表現可能な値)です。
例えば、1e23 - 8.5e6
をGoのfloat64
で計算し、その値をfmt.Printf("%.0f", value)
などで出力すると、99999999999999974834176
という結果が得られます。これは、1e23 - 8.5e6
という十進数の計算結果が、float64
の精度では99999999999999974834176
に丸められることを意味します。
同様に、1e23 + 8.5e6
をfloat64
で計算すると、100000000000000008388608
に丸められます。
これらの正確なfloat64
表現を定数として使用することで、テストは浮動小数点数の丸め誤差の影響を受けなくなり、ftoa
関数がこれらの特定の、かつ正確に表現可能なfloat64
値に対して正しく動作するかを検証できるようになります。これにより、テストの信頼性が向上し、異なる環境でのテスト結果の不一致を防ぐことができます。
コアとなるコードの変更箇所
変更はsrc/lib/strconv/ftoa_test.go
ファイルに集中しています。
--- a/src/lib/strconv/ftoa_test.go
+++ b/src/lib/strconv/ftoa_test.go
@@ -18,6 +18,11 @@ type Test struct {
func fdiv(a, b float64) float64 { return a / b } // keep compiler in the dark
+const (
+ Below1e23 = 99999999999999974834176;
+ Above1e23 = 100000000000000008388608;
+)
+
// TODO: Should be able to call this tests but it conflicts with testatof.go
var ftests = []Test {
Test{ 1, 'e', 5, "1.00000e+00" },
@@ -61,21 +66,21 @@ var ftests = []Test {
Test{ 1e23, 'f', -1, "100000000000000000000000" },
Test{ 1e23, 'g', -1, "1e+23" },
- Test{ 1e23-8.5e6, 'e', 17, "9.99999999999999748e+22" },
- Test{ 1e23-8.5e6, 'f', 17, "99999999999999974834176.00000000000000000" },
- Test{ 1e23-8.5e6, 'g', 17, "9.9999999999999975e+22" },
+ Test{ Below1e23, 'e', 17, "9.99999999999999748e+22" },
+ Test{ Below1e23, 'f', 17, "99999999999999974834176.00000000000000000" },
+ Test{ Below1e23, 'g', 17, "9.9999999999999975e+22" },
- Test{ 1e23-8.5e6, 'e', -1, "9.999999999999997e+22" },
- Test{ 1e23-8.5e6, 'f', -1, "99999999999999970000000" },
- Test{ 1e23-8.5e6, 'g', -1, "9.999999999999997e+22" },
+ Test{ Below1e23, 'e', -1, "9.999999999999997e+22" },
+ Test{ Below1e23, 'f', -1, "99999999999999970000000" },
+ Test{ Below1e23, 'g', -1, "9.999999999999997e+22" },
- Test{ 1e23+8.5e6, 'e', 17, "1.00000000000000008e+23" },
- Test{ 1e23+8.5e6, 'f', 17, "100000000000000008388608.00000000000000000" },
- Test{ 1e23+8.5e6, 'g', 17, "1.0000000000000001e+23" },
+ Test{ Above1e23, 'e', 17, "1.00000000000000008e+23" },
+ Test{ Above1e23, 'f', 17, "100000000000000008388608.00000000000000000" },
+ Test{ Above1e23, 'g', 17, "1.0000000000000001e+23" },
- Test{ 1e23+8.5e6, 'e', -1, "1.0000000000000001e+23" },
- Test{ 1e23+8.5e6, 'f', -1, "100000000000000010000000" },
- Test{ 1e23+8.5e6, 'g', -1, "1.0000000000000001e+23" },
+ Test{ Above1e23, 'e', -1, "1.0000000000000001e+23" },
+ Test{ Above1e23, 'f', -1, "100000000000000010000000" },
+ Test{ Above1e23, 'g', -1, "1.0000000000000001e+23" },
コアとなるコードの解説
-
定数の追加:
const
ブロックが追加され、Below1e23
とAbove1e23
という2つのfloat64
定数が定義されています。Below1e23 = 99999999999999974834176
Above1e23 = 100000000000000008388608
これらの値は、それぞれ1e23 - 8.5e6
と1e23 + 8.5e6
がfloat64
型として表現される際の、最も正確な十進数表現です。これにより、テストで使用される浮動小数点値が、コンパイラや実行環境による丸め誤差の影響を受けず、常に同じ正確な値になることが保証されます。
-
テストケースの更新:
ftests
スライス内の複数のTest
構造体の初期化において、元の1e23-8.5e6
と1e23+8.5e6
という浮動小数点リテラルが、新しく定義された定数Below1e23
とAbove1e23
に置き換えられています。 これにより、これらのテストケースは、浮動小数点数の計算結果に依存するのではなく、float64
型で正確に表現される既知の定数に対してftoa
関数の動作を検証するようになります。これは、テストの信頼性と再現性を大幅に向上させます。
この変更は、Go言語の初期段階における浮動小数点数処理の厳密性への配慮を示しており、テストの堅牢性を高めるための重要な改善です。
関連リンク
- IEEE 754 浮動小数点数標準: 浮動小数点数の表現と演算に関する国際標準。
- Go言語の
strconv
パッケージ: 文字列と基本データ型(数値、真偽値など)の相互変換を提供するパッケージ。ftoa
関数は、このパッケージの一部として機能します。
参考にした情報源リンク
- Go言語のソースコード:
src/lib/strconv/ftoa_test.go
- IEEE 754 - Wikipedia: https://ja.wikipedia.org/wiki/IEEE_754
- Go言語
strconv
パッケージドキュメント: https://pkg.go.dev/strconv - 浮動小数点数 - Wikipedia: https://ja.wikipedia.org/wiki/%E6%B5%AE%E5%8B%95%E5%B0%8F%E6%95%B0%E7%82%B9%E6%95%B0
- 倍精度浮動小数点数 - Wikipedia: https://ja.wikipedia.org/wiki/%E5%80%8D%E7%B2%BE%E5%BA%A6%E6%B5%AE%E5%8B%95%E5%B0%8F%E6%95%B0%E7%82%B9%E6%95%B0
- Russ CoxのGitHubプロフィール: https://github.com/rsc
- Go言語の初期コミット履歴 (GitHub): https://github.com/golang/go/commits/master?after=548609654311809b904f2b5a0926f3b38b45b7b4+1
- 浮動小数点数の正確な値を確認するためのオンラインツールやプログラミング言語のインタプリタ(例: Pythonの
float.as_integer_ratio()
やGoのfmt.Printf("%f", ...)
など)