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

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

このコミットは、Go言語の公式ドキュメントの一部である doc/code.html 内のコード例を修正し、newmath.Sqrt 関数のテストケースが確実に成功するように更新するものです。具体的には、テストの入力値と期待される出力値を変更することで、浮動小数点演算の精度に起因する潜在的なテスト失敗を防ぎ、ドキュメントの正確性を向上させています。

コミット

commit 25e02d519d205f7424fdc2a1e6926d3dee6544b4
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Tue Apr 10 01:55:51 2012 +0800

    doc/code: update newmath.Sqrt test case to make sure test succeed
            Fixes #3445.
    
    R=golang-dev, rsc, mtj
    CC=golang-dev
    https://golang.org/cl/5975061

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

https://github.com/golang/go/commit/25e02d519d205f7424fdc2a1e6926d3dee6544b4

元コミット内容

doc/code: update newmath.Sqrt test case to make sure test succeed
        Fixes #3445.

R=golang-dev, rsc, mtj
CC=golang-dev
https://golang.org/cl/5975061

変更の背景

この変更は、Go言語のIssue #3445 を修正するために行われました。Issue #3445は、doc/code.html に記載されている newmath.Sqrt 関数のテストケースが、特定の環境やGoのバージョンにおいて、浮動小数点演算の精度問題により失敗する可能性があるという報告でした。

元のテストケースでは Sqrt(9) の結果が 3 であることを期待していましたが、浮動小数点数の平方根計算は、厳密に整数値になる場合でも、内部的には浮動小数点数として扱われるため、ごくわずかな誤差が生じることがあります。この誤差が原因で、x != out という厳密な比較が true となり、テストが失敗する可能性がありました。

ドキュメント内のコード例は、読者がGoの機能やテストの書き方を学ぶためのものであり、環境によってテストが失敗するような不安定な例は避けるべきです。そのため、より安定して成功するテストケースに更新する必要がありました。

前提知識の解説

Go言語のテスト

Go言語には、標準ライブラリとしてテストフレームワークが組み込まれています。テストファイルは通常、テスト対象のGoファイルと同じディレクトリに _test.go というサフィックスを付けて配置されます。テスト関数は Test で始まり、*testing.T 型の引数を取ります。

  • go test: Goのテストを実行するためのコマンドです。指定されたパッケージ内の _test.go ファイルを見つけ、テスト関数を実行します。
  • testing.T: テストの実行中にエラーを報告したり、テストの進行状況を制御したりするためのメソッドを提供します。
    • t.Errorf(...): テストが失敗したことを報告し、指定されたフォーマット文字列と引数でエラーメッセージを出力します。テストは続行されます。
    • t.Fatalf(...): テストが失敗したことを報告し、エラーメッセージを出力した後、テストの実行を停止します。
  • const: Goにおける定数宣言です。コンパイル時に値が決定され、不変です。
  • package newmath: この例では、newmath という名前のパッケージが定義されており、その中に Sqrt 関数が含まれていることを示唆しています。これは、Goのパッケージ構造と、関数が特定のパッケージに属するという概念を示しています。

浮動小数点演算の精度

コンピュータにおける浮動小数点数(float32, float64 など)の表現は、有限のビット数で行われるため、すべての実数を正確に表現できるわけではありません。特に、平方根のような演算では、結果が厳密な整数値であっても、内部的にはわずかな誤差を含む浮動小数点数となることがあります。

例えば、math.Sqrt(9.0)3.0 を返しますが、これは float64 型の 3.0 であり、厳密には 3 という整数値とは異なるバイナリ表現を持つ可能性があります。そのため、x == 3 のような厳密な等価比較は、予期せぬ false を返すことがあります。このような場合、通常は許容誤差(epsilon)を設けて比較を行うか、テストケース自体を厳密な浮動小数点比較が不要なものに変更します。

技術的詳細

このコミットは、doc/code.html ファイル内のGoコード例を修正しています。このファイルは、Goの公式ドキュメントの一部であり、Goの基本的な使い方やテストの書き方を示すためのものです。

変更の核心は、newmath.Sqrt 関数のテストケースにおける入力値と期待される出力値の変更です。

  • 変更前:

    func TestSqrt(t *testing.T) {
    	const in, out = 9, 3
    	if x := Sqrt(in); x != out {
    		t.Errorf("Sqrt(%v) = %v, want %v", in, x, out)
        }
    }
    

    ここでは、in9out3 と設定されていました。Sqrt(9) の結果が厳密に 3 となることを期待していましたが、前述の浮動小数点数の精度問題により、Sqrt(9) の結果が 3.0000000000000004 のような値になり、x != outtrue と評価されてテストが失敗する可能性がありました。

  • 変更後:

    func TestSqrt(t *testing.T) {
    	const in, out = 4, 2
    	if x := Sqrt(in); x != out {
    		t.Errorf("Sqrt(%v) = %v, want %v", in, x, out)
        }
    }
    

    変更後では、in4out2 に設定されています。Sqrt(4) の結果も浮動小数点数として 2.0 に非常に近い値になりますが、9 の平方根よりも 4 の平方根の方が、多くの浮動小数点表現においてより正確に 2.0 として表現されやすい、あるいは誤差がテストの厳密な比較に影響を与えにくいという特性があります。この変更により、テストがより安定して成功するようになりました。

また、go test の出力例も更新されています。

  • 変更前:
    $ go test example/newmath
    ok  	example/newmath
    
  • 変更後:
    $ go test example/newmath
    ok  	example/newmath 0.165s
    
    これは、go test コマンドがテスト実行にかかった時間(0.165s)も出力するようになったことを反映しています。これはGoのテストツールの進化に伴うドキュメントの更新です。

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

--- a/doc/code.html
+++ b/doc/code.html
@@ -384,7 +384,7 @@ package newmath
 import "testing"
 
 func TestSqrt(t *testing.T) {
-	const in, out = 9, 3
+	const in, out = 4, 2
  	if x := Sqrt(in); x != out {
  	\tt.Errorf("Sqrt(%v) = %v, want %v", in, x, out)
         }
@@ -397,7 +397,7 @@ Now run the test with <code>go test</code>:
 
 <pre>
 $ go test example/newmath
-ok  	example/newmath
+ok  	example/newmath 0.165s
 </pre>
 
 <p>

コアとなるコードの解説

上記の差分は、doc/code.html ファイル内の2つの主要な変更を示しています。

  1. テストケースの入力値と期待値の変更:

    • const in, out = 9, 3const in, out = 4, 2 に変更されました。
    • これは、TestSqrt 関数内で使用される定数 inout の値を更新しています。inSqrt 関数への入力、out はその期待される出力です。この変更の目的は、Sqrt(9) が浮動小数点演算の精度問題によりテストが不安定になる可能性があったため、より安定してテストが成功する Sqrt(4) のケースに変更することです。4 の平方根は 2 であり、多くの浮動小数点表現でより正確に表現されやすいため、テストの信頼性が向上します。
  2. go test 出力例の更新:

    • ok example/newmathok example/newmath 0.165s に変更されました。
    • これは、go test コマンドの出力形式が更新され、テスト実行にかかった時間も表示されるようになったことを反映しています。ドキュメントのコード例と実際のコマンド出力が一致するように修正されました。

これらの変更は、Goのドキュメントの正確性と、読者がコード例を試した際の体験の安定性を向上させることを目的としています。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント (特にテストに関するセクション)
  • 浮動小数点数の精度に関する一般的な情報 (IEEE 754など)
  • GitHubのGoリポジトリのIssue #3445の議論内容
  • Goのコードレビューシステム (Gerrit) のCL 5975061の内容