Go言語 big.Int.DivMod()徹底解説:巨大整数除算と剰余の完全ガイド

2025-06-01

big.Int.DivMod()とは?

big.Int.DivMod()は、Go言語のmath/bigパッケージに用意されている関数で、非常に大きな整数(big.Int型)の除算と剰余を同時に計算するためのものです。通常のint型やint64型では扱えないような、任意精度の整数を扱う際に利用されます。

関数のシグネチャ(定義)

func (z *Int) DivMod(x, y, m *Int) (*Int, *Int)

引数

  • m: 計算結果である剰余が格納される*big.Int型のポインタ。
  • y: 除数(割る数)となる*big.Int型のポインタ。yが0の場合はランタイムパニックが発生します。
  • x: 被除数(割られる数)となる*big.Int型のポインタ。
  • z: 計算結果であるが格納される*big.Int型のポインタ。

戻り値

  • (z, m): 計算された商と剰余が格納された*big.Int型のポインタのペア。

動作

DivModは、zxyで割ったx div y)を、m剰余x mod y)を設定し、そのペア(z, m)を返します。

重要な点:ユークリッド除法

DivModは、Go言語の通常の/演算子や%演算子とは異なり、**ユークリッド除法(Euclidean division)**を実装しています。

ユークリッド除法とは、以下の関係が常に成り立つような商 q と剰余 m を定義するものです。

x=y×q+m

かつ、

0≤m<∣y∣ (剰余 m は常に非負で、除数 y の絶対値よりも小さい)

この定義により、xy が負の数であっても、剰余が常に非負になるという特徴があります。


  • DivMod(-10, -3): 商 4、剰余 2 (−10=(−3)×4+2)
  • DivMod(10, -3): 商 -3、剰余 1 (10=(−3)×(−3)+1)
  • DivMod(-10, 3): 商 -4、剰余 2 (−10=3×(−4)+2)
  • DivMod(10, 3): 商 3、剰余 1

Go言語の通常の演算子との違い

Go言語の通常の/演算子と%演算子は「切り捨て除算(truncated division)」に基づいています。これは、商が0方向に切り捨てられ、剰余の符号は被除数と同じになるというものです。

例(通常のGo言語の演算子)

  • -10 / -3 = 3, -10 % -3 = -1
  • 10 / -3 = -3, 10 % -3 = 1
  • -10 / 3 = -3, -10 % 3 = -1
  • 10 / 3 = 3, 10 % 3 = 1

このように、負の数の除算や剰余の計算において、big.Int.DivMod()の挙動はGoの組み込み演算子とは異なるため、注意が必要です。ユークリッド除法が必要な場合はDivModを、Goの組み込み演算子と同じ挙動が必要な場合はbig.Int.QuoRem()を使用します。

package main

import (
	"fmt"
	"math/big"
)

func main() {
	// 例1: 正の数 ÷ 正の数
	x1 := big.NewInt(10)
	y1 := big.NewInt(3)
	z1 := new(big.Int) // 商を格納するInt
	m1 := new(big.Int) // 剰余を格納するInt
	z1, m1 = z1.DivMod(x1, y1, m1)
	fmt.Printf("10 div 3: 商 = %s, 剰余 = %s\n", z1.String(), m1.String()) // 出力: 商 = 3, 剰余 = 1

	// 例2: 負の数 ÷ 正の数
	x2 := big.NewInt(-10)
	y2 := big.NewInt(3)
	z2 := new(big.Int)
	m2 := new(big.Int)
	z2, m2 = z2.DivMod(x2, y2, m2)
	fmt.Printf("-10 div 3: 商 = %s, 剰余 = %s\n", z2.String(), m2.String()) // 出力: 商 = -4, 剰余 = 2 (ユークリッド除法)

	// 例3: 正の数 ÷ 負の数
	x3 := big.NewInt(10)
	y3 := big.NewInt(-3)
	z3 := new(big.Int)
	m3 := new(big.Int)
	z3, m3 = z3.DivMod(x3, y3, m3)
	fmt.Printf("10 div -3: 商 = %s, 剰余 = %s\n", z3.String(), m3.String()) // 出力: 商 = -3, 剰余 = 1 (ユークリッド除法)

	// 例4: 負の数 ÷ 負の数
	x4 := big.NewInt(-10)
	y4 := big.NewInt(-3)
	z4 := new(big.Int)
	m4 := new(big.Int)
	z4, m4 = z4.DivMod(x4, y4, m4)
	fmt.Printf("-10 div -3: 商 = %s, 剰余 = %s\n", z4.String(), m4.String()) // 出力: 商 = 4, 剰余 = 2 (ユークリッド除法)

	// 注意: 割り算の結果を格納するIntは、既存のIntを使用するか、new(big.Int)で新しく作成する必要があります。
	// DivModはレシーバ (z) と第3引数 (m) を結果として更新し、それらを戻り値としても返します。
	// このため、例えば以下のように簡略化して書くことも可能です。
	quotient, remainder := new(big.Int).DivMod(big.NewInt(17), big.NewInt(5), new(big.Int))
	fmt.Printf("17 div 5: 商 = %s, 剰余 = %s\n", quotient.String(), remainder.String())
}


big.Int.DivMod()は、Goの組み込み型では扱えない大きな整数を扱う上で非常に便利な関数ですが、その特性上、いくつか注意すべき点があります。

除数 y が0の場合のパニック (runtime panic: division by zero)

エラーの状況
除数として指定するy0の場合、big.Int.DivMod()runtime panic: division by zeroを発生させます。これは通常の整数除算と同様の挙動です。

コード例

package main

import (
	"fmt"
	"math/big"
)

func main() {
	x := big.NewInt(100)
	y := big.NewInt(0) // ゼロ除算を引き起こす
	z := new(big.Int)
	m := new(big.Int)

	// ここでパニックが発生する
	z.DivMod(x, y, m)
	fmt.Printf("商: %s, 剰余: %s\n", z.String(), m.String())
}

トラブルシューティング
DivMod()を呼び出す前に、除数yが0でないことを確認する条件分岐を追加することが重要です。

package main

import (
	"fmt"
	"math/big"
)

func main() {
	x := big.NewInt(100)
	y := big.NewInt(0)
	z := new(big.Int)
	m := new(big.Int)

	if y.Cmp(big.NewInt(0)) == 0 { // yが0と比較して等しい場合
		fmt.Println("エラー: 除数が0です。")
		return // または適切なエラーハンドリング
	}

	z.DivMod(x, y, m)
	fmt.Printf("商: %s, 剰余: %s\n", z.String(), m.String())
}
  • y.Cmp(big.NewInt(0))は、y0を比較し、y0と等しい場合は0を返します。

ユークリッド除法と切り捨て除法の混同

エラーの状況
big.Int.DivMod()ユークリッド除法を採用しているため、負の数の除算において、Goの組み込み演算子 (/, %) とは異なる結果を返します。この違いを理解せずにコードを書くと、期待しない結果になることがあります。

例(再掲)

  • Go組み込み演算子: -10 / 3 = -3, -10 % 3 = -1
  • big.Int.DivMod(-10, 3): 商 -4、剰余 2

トラブルシューティング

  • Goの組み込み演算子と同じ挙動が必要な場合
    big.Int.QuoRem()を使用します。これはGoの組み込み演算子と同じ「切り捨て除算」に基づいています。
  • DivModが必要な場合
    剰余を常に非負にしたい、または数学的な厳密さでユークリッド除法が必要な場合はDivModを使用します。
package main

import (
	"fmt"
	"math/big"
)

func main() {
	x := big.NewInt(-10)
	y := big.NewInt(3)

	// DivMod (ユークリッド除法)
	qDivMod := new(big.Int)
	rDivMod := new(big.Int)
	qDivMod, rDivMod = qDivMod.DivMod(x, y, rDivMod)
	fmt.Printf("DivMod(-10, 3): 商 = %s, 剰余 = %s\n", qDivMod.String(), rDivMod.String()) // 商 = -4, 剰余 = 2

	// QuoRem (切り捨て除法)
	qQuoRem := new(big.Int)
	rQuoRem := new(big.Int)
	qQuoRem, rQuoRem = qQuoRem.QuoRem(x, y, rQuoRem)
	fmt.Printf("QuoRem(-10, 3): 商 = %s, 剰余 = %s\n", qQuoRem.String(), rQuoRem.String()) // 商 = -3, 剰余 = -1

	// 組み込み演算子
	fmt.Printf("Go組み込み: -10 / 3 = %d, -10 %% 3 = %d\n", -10/3, -10%3) // -10 / 3 = -3, -10 % 3 = -1
}

コードの意図に合わせて適切な関数を選択することが重要です。

引数のポインタ渡しと結果の再利用

エラーの状況
DivMod()は、レシーバzと第3引数mに計算結果を書き込みます。これらの引数には*big.Int型のポインタを渡す必要があります。また、引数として渡すbig.Intインスタンスを適切に初期化しないと、ゼロ値のbig.Intが使われたり、予期せぬ動作につながる可能性があります。

よくある誤解

  • 結果を格納するbig.Intnew(big.Int)で初期化せずに、単にvar z big.Intのように宣言するだけの場合、結果が正しく書き込まれない可能性がある(ただし、これはメソッドのレシーバがポインタであるため、コンパイルエラーになることが多い)。
  • big.Intのポインタではなく、値そのものを渡そうとする(コンパイルエラーになる)。

トラブルシューティング

  • 既存のbig.Intインスタンスを再利用する場合も、そのインスタンスのポインタを渡す。
  • new(big.Int)を使って新しいbig.Intインスタンスを初期化し、そのポインタを渡す。
package main

import (
	"fmt"
	"math/big"
)

func main() {
	x := big.NewInt(25)
	y := big.NewInt(7)

	// 正しい使い方: new(big.Int) で初期化
	quotient := new(big.Int)
	remainder := new(big.Int)

	// DivModはレシーバと第3引数を更新し、それらを戻り値としても返す
	quotient.DivMod(x, y, remainder)
	fmt.Printf("商: %s, 剰余: %s\n", quotient.String(), remainder.String())

	// 戻り値を直接受け取るパターン (より一般的)
	q, r := new(big.Int).DivMod(big.NewInt(25), big.NewInt(7), new(big.Int))
	fmt.Printf("商: %s, 剰余: %s\n", q.String(), r.String())

	// 既存の big.Int を再利用する例
	a := big.NewInt(50)
	b := big.NewInt(8)
	// quotient と remainder を再利用
	quotient.DivMod(a, b, remainder)
	fmt.Printf("商: %s, 剰余: %s\n", quotient.String(), remainder.String())
}

不変性に関する誤解 (大きな問題ではないが、意識しておくべき点)

エラーの状況
big.Intのメソッドは、多くの場合、レシーバ(メソッドを呼び出すインスタンス)を変更し、そのレシーバ自身を返します。DivModも同様に、商をレシーバzに書き込み、zを戻り値として返します。剰余は第3引数mに書き込まれ、mも戻り値として返されます。

これはエラーというよりは設計思想の理解の問題ですが、big.Intの操作では、元の値を保持したい場合は明示的にコピーを作成する必要があることを意識しておくべきです。

トラブルシューティング
元のbig.Intの値を保持したまま計算を行いたい場合は、big.Int.Set()big.Int.Add()などのメソッドを使用する前に、new(big.Int).Set(originalInt)のようにコピーを作成します。

package main

import (
	"fmt"
	"math/big"
)

func main() {
	originalX := big.NewInt(100)
	y := big.NewInt(7)

	// originalX の値を変更せずにDivModの結果を得たい場合
	// 方法1: new(big.Int) を使って新しいインスタンスに結果を格納
	quotient := new(big.Int)
	remainder := new(big.Int)
	quotient.DivMod(originalX, y, remainder) // originalX は変更されない

	fmt.Printf("元のX: %s\n", originalX.String())
	fmt.Printf("商: %s, 剰余: %s\n", quotient.String(), remainder.String())

	// 方法2: 戻り値を直接受け取る(これがより一般的で推奨される)
	// この場合も、元の引数は変更されない
	q, r := new(big.Int).DivMod(originalX, y, new(big.Int))
	fmt.Printf("商: %s, 剰余: %s\n", q.String(), r.String())
}

big.Int.DivMod()を使用する際の主なポイントは以下の通りです。

  1. ゼロ除算の回避
    除数が0にならないように常にチェックする。
  2. ユークリッド除法の理解
    負の数の扱いがGoの組み込み演算子と異なるため、QuoRemとの違いを理解し、目的に応じて使い分ける。
  3. ポインタの適切な利用
    引数および結果を格納するbig.Intはポインタで渡し、必要に応じてnew(big.Int)で初期化する。


big.Int.DivMod()は、巨大な整数の除算と剰余を同時に計算する際に使用されます。特に、剰余が常に非負となる「ユークリッド除法」が必要な場合に役立ちます。

例1: 基本的な正の数の除算と剰余

最も基本的な使い方です。10を3で割った商と剰余を計算します。

package main

import (
	"fmt"
	"math/big"
)

func main() {
	fmt.Println("--- 例1: 基本的な正の数の除算と剰余 ---")

	// 被除数 (割られる数) を10に設定
	x := big.NewInt(10)
	// 除数 (割る数) を3に設定
	y := big.NewInt(3)

	// 商と剰余を格納するための big.Int 型のポインタを初期化
	// new(big.Int) は、big.Int 型のゼロ値(0)を持つ新しいインスタンスを作成し、そのポインタを返します。
	quotient := new(big.Int)   // 商 (quotient)
	remainder := new(big.Int) // 剰余 (remainder)

	// DivMod メソッドを呼び出す
	// quotient.DivMod(x, y, remainder) は、x を y で割った商を quotient に、
	// 剰余を remainder に格納します。
	// そして、(quotient, remainder) のペアを戻り値としても返します。
	quotient.DivMod(x, y, remainder)

	// 結果を出力
	// String() メソッドは big.Int の値を文字列として返します。
	fmt.Printf("%s を %s で割ると:\n", x.String(), y.String())
	fmt.Printf("  商     = %s\n", quotient.String())  // 期待値: 3
	fmt.Printf("  剰余   = %s\n", remainder.String()) // 期待値: 1
}

解説
この例では、big.NewInt(value)を使ってbig.Int型のインスタンスを作成し、DivModに渡しています。quotientremainderは計算結果が書き込まれるプレースホルダーとして機能します。

例2: 負の数の除算とユークリッド除法

big.Int.DivMod()がユークリッド除法を実装していることを示す例です。Goの通常の/%演算子とは異なる結果になる点に注目してください。

package main

import (
	"fmt"
	"math/big"
)

func main() {
	fmt.Println("\n--- 例2: 負の数の除算とユークリッド除法 ---")

	testCases := []struct {
		x, y int64
	}{
		{-10, 3},  // xが負、yが正
		{10, -3},  // xが正、yが負
		{-10, -3}, // xが負、yが負
	}

	for _, tc := range testCases {
		x := big.NewInt(tc.x)
		y := big.NewInt(tc.y)

		qDivMod := new(big.Int)
		rDivMod := new(big.Int)
		qDivMod.DivMod(x, y, rDivMod)

		fmt.Printf("DivMod(%s, %s):\n", x.String(), y.String())
		fmt.Printf("  商 (DivMod)     = %s\n", qDivMod.String())
		fmt.Printf("  剰余 (DivMod)   = %s\n", rDivMod.String())

		// 参考として、Goの組み込み演算子 (`/`, `%`) の結果も表示
		// big.Int.QuoRem() は組み込み演算子と同じ切り捨て除法を行う
		qQuoRem := new(big.Int)
		rQuoRem := new(big.Int)
		qQuoRem.QuoRem(x, y, rQuoRem)

		fmt.Printf("  商 (QuoRem)     = %s\n", qQuoRem.String())
		fmt.Printf("  剰余 (QuoRem)   = %s\n", rQuoRem.String())

		// Go組み込み型での計算 (int64に収まる範囲で)
		fmt.Printf("  Go組み込み (%d / %d) = 商: %d, 剰余: %d\n\n", tc.x, tc.y, tc.x/tc.y, tc.x%tc.y)
	}
}

解説
この例は、DivModがユークリッド除法(剰余が常に非負で、0 <= 剰余 < |除数|)を適用することを示しています。QuoRem関数と比較することで、その違いが明確になります。組み込みの/%演算子はQuoRemと同じ「切り捨て除算」を行います。

例3: ゼロ除算のハンドリング

DivModに除数として0を渡すとパニックが発生するため、事前にチェックする方法を示します。

package main

import (
	"fmt"
	"math/big"
)

func main() {
	fmt.Println("--- 例3: ゼロ除算のハンドリング ---")

	x := big.NewInt(12345)
	y := big.NewInt(0) // ゼロ除算を引き起こす除数

	quotient := new(big.Int)
	remainder := new(big.Int)

	// 除数が0かどうかをチェック
	// y.Cmp(big.NewInt(0)) == 0 は、yが0と等しい場合にtrueを返します。
	if y.Cmp(big.NewInt(0)) == 0 {
		fmt.Printf("エラー: 除数 %s がゼロです。除算できません。\n", y.String())
		// ここでエラーを返す、ログに記録する、またはプログラムを終了するなどの処理を行います。
		return
	}

	// ゼロでなければ安全に DivMod を呼び出す
	quotient.DivMod(x, y, remainder)
	fmt.Printf("%s を %s で割ると:\n", x.String(), y.String())
	fmt.Printf("  商     = %s\n", quotient.String())
	fmt.Printf("  剰余   = %s\n", remainder.String())
}

解説
big.Int.Cmp()メソッドは、2つのbig.Intの比較結果を返します。

  • a.Cmp(b)が正の場合、a > b。 この性質を利用して、除数yが0であるかをチェックしています。
  • a.Cmp(b)が負の場合、a < b
  • a.Cmp(b)が0の場合、abは等しい。

例4: 戻り値を直接受け取る簡潔な書き方

DivModは、レシーバと第3引数を更新するだけでなく、その2つのポインタを戻り値としても返すため、より簡潔に書くことができます。

package main

import (
	"fmt"
	"math/big"
)

func main() {
	fmt.Println("\n--- 例4: 戻り値を直接受け取る簡潔な書き方 ---")

	// new(big.Int).DivMod(...) のように、メソッドチェーンで記述できます。
	// この場合、商と剰余を格納するための新しい big.Int インスタンスがその場で作成されます。
	// 被除数と除数も一時的な big.Int インスタンスとして作成されます。
	quotient, remainder := new(big.Int).DivMod(big.NewInt(100), big.NewInt(17), new(big.Int))

	fmt.Printf("100 を 17 で割ると:\n")
	fmt.Printf("  商     = %s\n", quotient.String())  // 期待値: 5
	fmt.Printf("  剰余   = %s\n", remainder.String()) // 期待値: 15

	// 負の数での例
	qNeg, rNeg := new(big.Int).DivMod(big.NewInt(-100), big.NewInt(17), new(big.Int))
	fmt.Printf("-100 を 17 で割ると(ユークリッド除法):\n")
	fmt.Printf("  商     = %s\n", qNeg.String())  // 期待値: -6
	fmt.Printf("  剰余   = %s\n", rNeg.String()) // 期待値: 2 ($-100 = 17 \times (-6) + 2$)
}

解説
この書き方は、一時的な計算結果を格納する変数名を別途宣言せずに済むため、非常に簡潔です。new(big.Int)は新しいゼロ値のbig.Intを作成し、そのポインタがDivModのレシーバおよび剰余の格納先として使用されます。



math/bigパッケージには、除算や剰余に関するいくつかのメソッドが提供されており、それぞれ異なる特性を持っています。

big.Int.QuoRem(): Goの組み込み演算子 (/, %) と同じ挙動

シグネチャ

func (z *Int) QuoRem(x, y, r *Int) (*Int, *Int)

引数

  • r: 計算結果である剰余が格納される*big.Int型のポインタ。
  • y: 除数となる*big.Int型のポインタ。yが0の場合はランタイムパニックが発生します。
  • x: 被除数となる*big.Int型のポインタ。
  • z: 計算結果であるが格納される*big.Int型のポインタ。

戻り値

  • (z, r): 計算された商と剰余が格納された*big.Int型のポインタのペア。

DivModとの使い分け

  • QuoRem: Goの通常のint型やint64型での/%と同じ結果を得たい場合。
  • DivMod: 剰余を常に非負にしたい、数学的なユークリッド除法が必要な場合。

コード例

package main

import (
	"fmt"
	"math/big"
)

func main() {
	fmt.Println("--- big.Int.QuoRem() の例 ---")

	x := big.NewInt(-10)
	y := big.NewInt(3)

	// QuoRem を使用
	// 商は -3、剰余は -1 (Goの組み込み演算子と同じ)
	qQuoRem := new(big.Int)
	rQuoRem := new(big.Int)
	qQuoRem.QuoRem(x, y, rQuoRem)
	fmt.Printf("QuoRem(%s, %s):\n", x.String(), y.String())
	fmt.Printf("  商 = %s\n", qQuoRem.String()) // -3
	fmt.Printf("  剰余 = %s\n", rQuoRem.String()) // -1

	// 比較のための DivMod
	qDivMod := new(big.Int)
	rDivMod := new(big.Int)
	qDivMod.DivMod(x, y, rDivMod)
	fmt.Printf("DivMod(%s, %s):\n", x.String(), y.String())
	fmt.Printf("  商 = %s\n", qDivMod.String()) // -4
	fmt.Printf("  剰余 = %s\n", rDivMod.String()) // 2
}

big.Int.Quo(): 商のみを計算

シグネチャ

func (z *Int) Quo(x, y *Int) *Int

引数

  • y: 除数となる*big.Int型のポインタ。yが0の場合はランタイムパニックが発生します。
  • x: 被除数となる*big.Int型のポインタ。
  • z: 計算結果であるが格納される*big.Int型のポインタ。

戻り値

  • z: 計算された商が格納された*big.Int型のポインタ。

コード例

package main

import (
	"fmt"
	"math/big"
)

func main() {
	fmt.Println("\n--- big.Int.Quo() の例 ---")

	x := big.NewInt(1234567890123456789)
	y := big.NewInt(98765)

	quotient := new(big.Int)
	quotient.Quo(x, y) // x を y で割った商を quotient に設定

	fmt.Printf("%s を %s で割った商 (Quo) = %s\n", x.String(), y.String(), quotient.String())

	// 負の数での例 (切り捨て除算)
	xNeg := big.NewInt(-20)
	yPos := big.NewInt(3)
	qNeg := new(big.Int)
	qNeg.Quo(xNeg, yPos)
	fmt.Printf("%s を %s で割った商 (Quo) = %s\n", xNeg.String(), yPos.String(), qNeg.String()) // 期待値: -6
}

big.Int.Rem(): 剰余のみを計算

シグネチャ

func (z *Int) Rem(x, y *Int) *Int

引数

  • y: 除数となる*big.Int型のポインタ。yが0の場合はランタイムパニックが発生します。
  • x: 被除数となる*big.Int型のポインタ。
  • z: 計算結果である剰余が格納される*big.Int型のポインタ。

戻り値

  • z: 計算された剰余が格納された*big.Int型のポインタ。

コード例

package main

import (
	"fmt"
	"math/big"
)

func main() {
	fmt.Println("\n--- big.Int.Rem() の例 ---")

	x := big.NewInt(25)
	y := big.NewInt(7)

	remainder := new(big.Int)
	remainder.Rem(x, y) // x を y で割った剰余を remainder に設定

	fmt.Printf("%s を %s で割った剰余 (Rem) = %s\n", x.String(), y.String(), remainder.String()) // 期待値: 4

	// 負の数での例 (被除数の符号に依存)
	xNeg := big.NewInt(-25)
	yPos := big.NewInt(7)
	rNeg := new(big.Int)
	rNeg.Rem(xNeg, yPos)
	fmt.Printf("%s を %s で割った剰余 (Rem) = %s\n", xNeg.String(), yPos.String(), rNeg.String()) // 期待値: -4
}

big.Int.Mod(): ユークリッド剰余のみを計算

シグネチャ

func (z *Int) Mod(x, y *Int) *Int

引数

  • y: 除数となる*big.Int型のポインタ。yが0の場合はランタイムパニックが発生します。
  • x: 被除数となる*big.Int型のポインタ。
  • z: 計算結果である剰余が格納される*big.Int型のポインタ。

戻り値

  • z: 計算された剰余が格納された*big.Int型のポインタ。
package main

import (
	"fmt"
	"math/big"
)

func main() {
	fmt.Println("\n--- big.Int.Mod() の例 ---")

	x := big.NewInt(-25)
	y := big.NewInt(7)

	modulo := new(big.Int)
	modulo.Mod(x, y) // x を y で割った剰余 (ユークリッド除法) を modulo に設定

	fmt.Printf("%s を %s で割った剰余 (Mod) = %s\n", x.String(), y.String(), modulo.String()) // 期待値: 3 ($-25 = 7 \times (-4) + 3$)

	// 比較のための Rem
	remainder := new(big.Int)
	remainder.Rem(x, y)
	fmt.Printf("%s を %s で割った剰余 (Rem) = %s\n", x.String(), y.String(), remainder.String()) // 期待値: -4
}
メソッド戻り値商の扱い剰余の符号主な用途
DivMod(x, y, m)(商, 剰余)ユークリッド非負商とユークリッド剰余を同時に取得したい場合
QuoRem(x, y, r)(商, 剰余)切り捨て被除数と同じ商とGoの組み込み演算子と同じ剰余を同時に取得
Quo(x, y)切り捨てなし商のみが必要で、Goの組み込み演算子と同じ挙動でよい場合
Rem(x, y)剰余なし被除数と同じ剰余のみが必要で、Goの組み込み演算子と同じ挙動でよい場合
Mod(x, y)剰余なし非負剰余のみが必要で、常に非負のユークリッド剰余が欲しい場合