[インデックス 11366] ファイルの概要
このコミットは、Go言語の標準ライブラリである math/big
パッケージに、Rat
型と Int
型の SetString
メソッドおよび Scan
メソッドの使用例を追加するものです。具体的には、src/pkg/math/big/example_test.go
という新しいテストファイルが作成され、これらのメソッドの具体的な利用方法が示されています。
コミット
commit ddd67f2ecd1c100c48563addf4293bfe6dc7535f
Author: Andrew Gerrand <adg@golang.org>
Date: Wed Jan 25 10:29:44 2012 +1100
math/big: add examples for Rat and Int's SetString and Scan methods
R=golang-dev, bradfitz, rsc, r, gri, r
CC=golang-dev
https://golang.org/cl/5543047
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/ddd67f2ecd1c100c48563addf4293bfe6dc7535f
元コミット内容
math/big: add examples for Rat and Int's SetString and Scan methods
R=golang-dev, bradfitz, rsc, r, gri, r
CC=golang-dev
https://golang.org/cl/5543047
変更の背景
Go言語の math/big
パッケージは、任意精度(arbitrary-precision)の整数、有理数、浮動小数点数を扱うための機能を提供します。これらの型は、標準のGoの数値型(int
, float64
など)では表現できない非常に大きな数値や、精度が要求される計算に用いられます。
SetString
メソッドは、文字列形式で表現された数値を対応する big.Int
や big.Rat
オブジェクトにパースして設定するために使用されます。一方、Scan
メソッドは、fmt
パッケージの Scanner
インターフェースを実装しており、fmt.Scan
や fmt.Sscan
などの関数を通じて、入力ストリームから数値を読み込む際に利用されます。
このコミットが作成された背景には、これらの重要なメソッドの利用方法を開発者により明確に示す必要があったことが考えられます。特に、Scan
メソッドは fmt
パッケージとの連携において暗黙的に呼び出されることが多いため、その動作を例示することは、ライブラリの使いやすさを向上させる上で非常に有効です。公式の例は、ドキュメントだけでは伝わりにくい具体的なコードの書き方や、エッジケースの扱い方を理解するのに役立ちます。
前提知識の解説
任意精度演算 (Arbitrary-Precision Arithmetic)
通常のプログラミング言語における数値型(例: Goの int64
, float64
)は、固定されたビット数で数値を表現します。これにより、表現できる数値の範囲や精度には限界があります。例えば、int64
は約9.22 × 10^18 までの整数しか扱えず、float64
は約15桁の精度しか保証しません。
これに対し、任意精度演算は、必要に応じてメモリを動的に割り当てることで、理論上は無限の桁数や精度を持つ数値を扱うことができます。Goの math/big
パッケージは、この任意精度演算をGo言語で実現するための機能を提供します。
big.Int
: 任意精度の整数を扱います。非常に大きな数値を正確に計算する場合に利用されます。big.Rat
: 任意精度の有理数(分数)を扱います。numerator/denominator
の形式で数値を表現し、浮動小数点数で発生する丸め誤差なしに正確な分数計算を行うことができます。
fmt.Scanner
インターフェース
Go言語の fmt
パッケージは、フォーマットされた入出力(printf/scanfスタイル)を提供します。fmt.Scan
, fmt.Sscan
, fmt.Fscan
などの関数は、入力から値を読み取るために使用されます。これらの関数は、読み取る型が fmt.Scanner
インターフェースを実装している場合、その Scan
メソッドを自動的に呼び出します。
fmt.Scanner
インターフェースは以下のように定義されています。
type Scanner interface {
Scan(state fmt.ScanState, verb rune) error
}
Scan
メソッドは、入力ストリームからデータを読み取り、それ自身(レシーバ)にその値を設定する責任を持ちます。math/big
パッケージの Int
および Rat
型がこのインターフェースを実装しているため、fmt
パッケージの走査関数を通じてこれらの型の値を直接読み込むことが可能になります。
SetString
メソッド
SetString
メソッドは、文字列形式で表現された数値をパースし、その値を big.Int
または big.Rat
オブジェクトに設定するために使用されます。
(*Int).SetString(s string, base int)
:s
: 数値を表す文字列。base
: 数値の基数(2から62まで)。例えば、10進数の場合は10
、8進数の場合は8
、16進数の場合は16
を指定します。base
が0
の場合、文字列のプレフィックス(0x
は16進数、0
は8進数)に基づいて基数を自動的に推測します。
(*Rat).SetString(s string)
:s
: 有理数を表す文字列。"numerator/denominator"
の形式(例:"3/2"
)または浮動小数点数形式(例:"1.5"
)で指定できます。
これらのメソッドは、文字列から数値オブジェクトへの変換という、任意精度演算において非常に基本的な操作を提供します。
技術的詳細
このコミットは、Goのテストフレームワークにおける「Example」関数を利用しています。Goの go test
コマンドは、Example
というプレフィックスを持つ関数を特別に扱います。これらの関数は、通常のテスト関数と同様に実行されますが、その標準出力(fmt.Println
など)がキャプチャされ、関数のコメントブロックに記述された期待される出力と比較されます。これにより、コードの動作例が常に最新かつ正確であることを保証し、同時にドキュメントとしても機能します。
example_test.go
ファイルは、Goのパッケージのテストファイル命名規則に従っています。_test.go
サフィックスを持つファイルは、テストコードを含むことを示し、package big_test
のように _test
サフィックスを付けることで、テスト対象のパッケージとは別のパッケージとしてテストを実行し、外部から見えるAPIのみをテストすることを保証します。
追加された例は以下の通りです。
ExampleRat_SetString
:big.Rat
型のインスタンスを作成し、SetString("355/113")
を呼び出して円周率の近似値(355/113)を設定します。FloatString(3)
を使用して、結果を小数点以下3桁の浮動小数点数として出力します。これは、有理数を浮動小数点数として表示する際の丸め処理を示しています。
ExampleInt_SetString
:big.Int
型のインスタンスを作成し、SetString("644", 8)
を呼び出して8進数文字列 "644" を整数に変換します。- 結果をそのまま出力し、8進数 "644" が10進数で何になるか(420)を示します。
ExampleRat_Scan
:big.Rat
型のインスタンスを作成します。fmt.Sscan("1.5000", r)
を使用して、文字列 "1.5000" から有理数を読み込みます。Scan
メソッドがfmt.Scanner
インターフェースの実装としてどのように機能するかを示します。エラーハンドリングも含まれています。
ExampleInt_Scan
:big.Int
型のインスタンスを作成します。fmt.Sscan("18446744073709551617", i)
を使用して、非常に大きな整数を文字列から読み込みます。Scan
メソッドがfmt.Scanner
インターフェースの実装として、大きな整数をどのように処理するかを示します。
これらの例は、math/big
パッケージの基本的な使い方を網羅しており、特に文字列との相互変換の重要性を示しています。
コアとなるコードの変更箇所
このコミットで追加されたファイルは src/pkg/math/big/example_test.go
のみです。
--- /dev/null
+++ b/src/pkg/math/big/example_test.go
@@ -0,0 +1,51 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package big_test
+
+import (
+ "fmt"
+ "log"
+ "math/big"
+)
+
+// 3.142
+func ExampleRat_SetString() {
+ r := new(big.Rat)
+ r.SetString("355/113")
+ fmt.Println(r.FloatString(3))
+}
+
+// 420
+func ExampleInt_SetString() {
+ i := new(big.Int)
+ i.SetString("644", 8) // octal
+ fmt.Println(i)
+}
+
+// 3/2
+func ExampleRat_Scan() {
+ // The Scan function is rarely used directly;
+ // the fmt package recognizes it as an implementation of fmt.Scanner.
+ r := new(big.Rat)
+ _, err := fmt.Sscan("1.5000", r)
+ if err != nil {
+ log.Println("error scanning value:", err)
+ } else {
+ fmt.Println(r)
+ }
+}
+
+// 18446744073709551617
+func ExampleInt_Scan() {
+ // The Scan function is rarely used directly;
+ // the fmt package recognizes it as an implementation of fmt.Scanner.
+ i := new(big.Int)
+ _, err := fmt.Sscan("18446744073709551617", i)
+ if err != nil {
+ log.Println("error scanning value:", err)
+ } else {
+ fmt.Println(i)
+ }
+}
コアとなるコードの解説
追加された example_test.go
ファイルは、math/big
パッケージの Rat
と Int
型の SetString
および Scan
メソッドの具体的な使用例を、GoのExampleテスト形式で提供しています。
ExampleRat_SetString()
この関数は big.Rat
型の SetString
メソッドの基本的な使い方を示しています。
r := new(big.Rat)
: 新しいbig.Rat
オブジェクトを初期化します。new
を使うことで、ポインタが返され、メソッド呼び出しでそのオブジェクトの状態を変更できます。r.SetString("355/113")
: 文字列"355/113"
をパースし、r
に有理数として設定します。これは円周率の近似値として知られる分数です。fmt.Println(r.FloatString(3))
:Rat
型の値を浮動小数点数として表示します。FloatString(3)
は、小数点以下3桁までで文字列を生成します。これにより、3.142
という出力が得られます。
ExampleInt_SetString()
この関数は big.Int
型の SetString
メソッドの基本的な使い方を示しています。
i := new(big.Int)
: 新しいbig.Int
オブジェクトを初期化します。i.SetString("644", 8)
: 文字列"644"
を基数8(8進数)としてパースし、i
に整数として設定します。8進数の644
は10進数で6*8^2 + 4*8^1 + 4*8^0 = 6*64 + 4*8 + 4*1 = 384 + 32 + 4 = 420
となります。fmt.Println(i)
:Int
型の値をそのまま出力します。これにより、420
という出力が得られます。
ExampleRat_Scan()
この関数は big.Rat
型が fmt.Scanner
インターフェースをどのように実装しているかを示します。
r := new(big.Rat)
: 新しいbig.Rat
オブジェクトを初期化します。_, err := fmt.Sscan("1.5000", r)
:fmt.Sscan
は文字列から値を読み取る関数です。r
がfmt.Scanner
インターフェースを実装しているため、fmt.Sscan
は内部的にr.Scan()
メソッドを呼び出し、文字列"1.5000"
をパースしてr
に設定します。- エラーハンドリング:
fmt.Sscan
がエラーを返した場合(例: 無効な入力形式)、log.Println
でエラーメッセージを出力します。 fmt.Println(r)
: 正常にスキャンされたRat
の値を出力します。1.5000
は3/2
として表現されます。
ExampleInt_Scan()
この関数は big.Int
型が fmt.Scanner
インターフェースをどのように実装しているかを示します。
i := new(big.Int)
: 新しいbig.Int
オブジェクトを初期化します。_, err := fmt.Sscan("18446744073709551617", i)
:fmt.Sscan
を使用して、非常に大きな整数を表す文字列をi
に読み込みます。この数値はuint64
の最大値18446744073709551615
をわずかに超える値であり、標準のint64
やuint64
では正確に表現できないことを示唆しています。big.Int
は任意精度であるため、このような大きな数値も正確に扱えます。- エラーハンドリング:
fmt.Sscan
がエラーを返した場合、エラーメッセージを出力します。 fmt.Println(i)
: 正常にスキャンされたInt
の値を出力します。
これらの例は、math/big
パッケージの SetString
と Scan
メソッドが、文字列と任意精度数値の間でどのように変換を行うか、そして fmt
パッケージとの統合がどのように機能するかを明確に示しています。
関連リンク
- Go言語
math/big
パッケージのドキュメント: https://pkg.go.dev/math/big - Go言語
fmt
パッケージのドキュメント: https://pkg.go.dev/fmt - Go言語のExampleテストに関する公式ブログ記事 (Go 1.4での変更点を含むが、Exampleの概念は共通): https://go.dev/blog/go1.4-examples
参考にした情報源リンク
- Go言語の公式ドキュメント (
pkg.go.dev
) - Go言語のGitHubリポジトリ (
github.com/golang/go
) - Go言語のExampleテストに関する一般的な情報源 (例: Go言語のブログ、技術記事)
- 任意精度演算に関する一般的な知識