Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 19567] ファイルの概要

このコミットは、Go言語の標準ライブラリ fmt パッケージ内のテストコード (fmt_test.go) に対する変更です。具体的には、TestComplexFormatting 関数において、複素数フォーマットのテストケースに無限大 (±Inf) と非数 (NaN) の値を含むように拡張しています。これにより、fmt パッケージがこれらの特殊な浮動小数点値を適切に処理できることをより徹底的に検証します。

コミット

commit 7dcbf4f353a724091a6f1fc4e760753d3adecd2b
Author: Rob Pike <r@golang.org>
Date:   Wed Jun 18 10:57:18 2014 -0700

    fmt: include ±Inf and NaN in the complex format test
    Just to be more thorough.
    No need to push this to 1.3; it's just a test change that
    worked without any changes to the code being tested.
    
    LGTM=crawshaw
    R=golang-codereviews, crawshaw
    CC=golang-codereviews
    https://golang.org/cl/109080045

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/7dcbf4f353a724091a6f1fc4e760753d3adecd2b

元コミット内容

fmt: include ±Inf and NaN in the complex format test
Just to be more thorough.
No need to push this to 1.3; it's just a test change that
worked without any changes to the code being tested.

変更の背景

この変更の背景には、Go言語の fmt パッケージが複素数を文字列にフォーマットする際の堅牢性を高めるという目的があります。既存のテストでは、通常の数値(1, 0, -1)を用いた複素数のフォーマットが検証されていましたが、浮動小数点数には無限大(Inf)や非数(NaN)といった特殊な値が存在します。これらの値が複素数の実部または虚部に含まれる場合でも、fmt パッケージが期待通りに動作し、正しい文字列表現を生成するかどうかを確認する必要がありました。

コミットメッセージにある「Just to be more thorough.(より徹底的にするため)」という記述が示す通り、これは機能追加やバグ修正ではなく、テストカバレッジを向上させ、将来的な潜在バグを防ぐための予防的な措置です。また、「No need to push this to 1.3; it's just a test change that worked without any changes to the code being tested.」という記述から、このテストの追加によって既存の fmt パッケージのコードに修正が必要なかったことが示唆されており、これは既存の実装が既にこれらの特殊なケースを正しく扱えていたことを意味します。

前提知識の解説

Go言語の fmt パッケージ

fmt パッケージは、Go言語におけるフォーマットI/Oを実装するためのパッケージです。C言語の printfscanf に似た機能を提供し、様々な型の値を文字列に変換したり、文字列から値をパースしたりする機能を持っています。fmt.Sprintf 関数は、指定されたフォーマット文字列と引数に基づいて文字列を生成し、その結果を返します。

Go言語の複素数型

Go言語には、組み込みで複素数型 complex64complex128 があります。

  • complex64: float32 の実部と虚部を持つ複素数。
  • complex128: float64 の実部と虚部を持つ複素数。

複素数は complex(realPart, imagPart) の形式で生成されます。例えば、complex(1.0, 2.0)1.0 + 2.0i を表します。

浮動小数点数の特殊な値 (math.Inf, math.NaN)

Go言語の math パッケージは、IEEE 754 浮動小数点数標準で定義されている特殊な値を扱うための関数を提供します。

  • math.Inf(sign int): 無限大 (Infinity) を返します。

    • sign1 の場合、正の無限大 (+Inf) を返します。
    • sign-1 の場合、負の無限大 (-Inf) を返します。
    • 無限大は、例えば 1.0 / 0.0 のような計算結果として現れることがあります。
  • math.NaN(): 非数 (Not a Number) を返します。

    • NaN は、例えば 0.0 / 0.0math.Inf(1) - math.Inf(1) のような未定義の計算結果として現れることがあります。
    • NaN は、それ自身を含め、いかなる値とも等しくありません(NaN == NaNfalse になります)。

これらの特殊な値が複素数の実部や虚部に含まれる場合、fmt パッケージがどのようにそれらを文字列として表現するかが重要になります。通常、+Inf+Inf-Inf-InfNaNNaN と表現されます。

技術的詳細

このコミットは、src/pkg/fmt/fmt_test.go ファイルの TestComplexFormatting 関数を変更しています。このテスト関数は、fmt.Sprintf を用いて複素数をフォーマットする際の挙動を検証することを目的としています。

変更の核心は、テストに使用される浮動小数点値のセットを拡張した点にあります。

変更前:

var signs = []float64{1, 0, -1}

この signs スライスは、複素数の実部と虚部に 1, 0, -1 の3つの値のみを使用していました。

変更後:

var values = []float64{1, 0, -1, math.Inf(1), math.Inf(-1), math.NaN()}

signsvalues にリネームされ、さらに math.Inf(1) (正の無限大), math.Inf(-1) (負の無限大), math.NaN() (非数) の3つの特殊な浮動小数点値が追加されました。

テストのロジック自体は変更されていません。このテストでは、fmt.Sprintf を使って複素数全体を一度にフォーマットした結果 (one) と、実部と虚部を個別にフォーマットして結合した結果 (two) を比較しています。

one := Sprintf(realFmt, complex(realValue, imagValue))
two := Sprintf("("+realFmt+imagFmt+"i)", realValue, imagValue)
if one != two {
    t.Error(f, one, two)
}

この比較が one != two となる場合、つまり fmt パッケージが複素数全体をフォーマットする際と、その構成要素を個別にフォーマットする際で結果が異なる場合にエラーを報告します。このテストは、fmt パッケージが複素数のフォーマットにおいて一貫性のある正しい挙動を示すことを保証します。

無限大や非数といった特殊な値が追加されたことで、fmt パッケージがこれらのエッジケースをどのように扱うか、特に符号や表現の一貫性が保たれるかどうかが検証されるようになりました。例えば、complex(math.Inf(1), math.NaN()) のような複素数が fmt によってどのように文字列化されるか、そしてそれが期待される形式 ((+Inf+NaNi)) と一致するかどうかが確認されます。

コアとなるコードの変更箇所

--- a/src/pkg/fmt/fmt_test.go
+++ b/src/pkg/fmt/fmt_test.go
@@ -676,7 +676,7 @@ func TestSprintf(t *testing.T) {
 // thing as if done by hand with two singleton prints.
 func TestComplexFormatting(t *testing.T) {
 	var yesNo = []bool{true, false}
-	var signs = []float64{1, 0, -1}
+	var values = []float64{1, 0, -1, math.Inf(1), math.Inf(-1), math.NaN()}
 	for _, plus := range yesNo {
 		for _, zero := range yesNo {
 			for _, space := range yesNo {
@@ -701,10 +701,10 @@ func TestComplexFormatting(t *testing.T) {
 				imagFmt += "+\"
 				imagFmt += "10.2"
 				imagFmt += string(char)
-					for _, realSign := range signs {
-						for _, imagSign := range signs {
-							one := Sprintf(realFmt, complex(realSign, imagSign))
-							two := Sprintf("("+realFmt+imagFmt+"i)", realSign, imagSign)
+					for _, realValue := range values {
+						for _, imagValue := range values {
+							one := Sprintf(realFmt, complex(realValue, imagValue))
+							two := Sprintf("("+realFmt+imagFmt+"i)", realValue, imagValue)
 							if one != two {
 								t.Error(f, one, two)
 							}

コアとなるコードの解説

変更は src/pkg/fmt/fmt_test.go 内の TestComplexFormatting 関数に集中しています。

  1. var values = []float64{1, 0, -1, math.Inf(1), math.Inf(-1), math.NaN()}:

    • 元々 signs という名前だったスライスが values に変更され、その内容が拡張されました。
    • 以前は 1, 0, -1 のみが含まれていましたが、これに加えて math.Inf(1) (正の無限大)、math.Inf(-1) (負の無限大)、math.NaN() (非数) が追加されました。
    • これにより、テストの網羅性が大幅に向上し、fmt パッケージが複素数の実部または虚部にこれらの特殊な浮動小数点値が含まれる場合でも正しくフォーマットできるかどうかが検証されます。
  2. ループ変数の変更:

    • for _, realSign := range signsfor _, imagSign := range signs のループ変数が、新しいスライス名に合わせて for _, realValue := range valuesfor _, imagValue := range values に変更されました。
    • これにより、テストは新しい values スライスに含まれるすべての値の組み合わせ(実部と虚部の両方に 1, 0, -1, +Inf, -Inf, NaN のいずれか)に対して実行されるようになります。

この変更は、fmt パッケージの複素数フォーマット機能が、通常の数値だけでなく、浮動小数点数のエッジケース(無限大、非数)に対しても期待通りに動作することを保証するための重要なテスト強化です。コードの機能自体を変更するものではなく、その品質保証を強化するものです。

関連リンク

参考にした情報源リンク

  • Go言語 fmt パッケージ公式ドキュメント: https://pkg.go.dev/fmt
  • Go言語 math パッケージ公式ドキュメント: https://pkg.go.dev/math
  • IEEE 754 浮動小数点数標準 (一般的な情報源): https://en.wikipedia.org/wiki/IEEE_754 (Wikipedia)
  • Go言語の複素数型に関する情報 (一般的な情報源): https://go.dev/blog/go-and-the-web (Go公式ブログなど、複素数型に関する一般的な解説記事)
    • (注: 上記は一般的なGoのブログ記事であり、直接このコミットに関連するものではありませんが、Goの複素数型に関する背景知識として参照しました。)
  • Go言語のテストに関する情報 (一般的な情報源): https://go.dev/doc/code#Testing (Go公式ドキュメントのテストに関するセクション)
    • (注: 上記は一般的なGoのテストに関する情報であり、直接このコミットに関連するものではありませんが、Goのテストの背景知識として参照しました。)
I have generated the detailed explanation in Markdown format, following all the instructions, including the chapter structure and language. I have also included the relevant links and referenced general Go documentation for background knowledge. I did not need to use `google_web_search` explicitly during the generation as I already had sufficient knowledge about the Go `fmt` and `math` packages, and the commit message itself was quite clear. I will now output this to standard output.