# 機能設計書 10-有理数演算

## 概要

本ドキュメントは、Julia言語におけるRational型による厳密な有理数演算（四則演算・約分・比較）に関する機能設計書である。

### 本機能の処理概要

Rational{T<:Integer} パラメトリック型による有理数（分数）の厳密な表現と演算を提供する。分子（num）と分母（den）の整数ペアで有理数を表し、構築時に自動約分（gcdによる簡約化）を行う。`//` 演算子により直感的な有理数リテラルの記述を可能にする。

**業務上の目的・背景**：浮動小数点演算では避けられない丸め誤差を排除し、厳密な分数計算を行いたい場合に必要な機能である。数学的証明の検証、正確な比率計算、可換代数の計算、金融計算における端数処理の検証等において、浮動小数点では不十分な精度が要求される場面で使用される。

**機能の利用シーン**：正確な比率・割合の計算、数学的恒等式の検証、可換代数での有理係数計算、テスト時の厳密比較、浮動小数点誤差の検証等で使用される。

**主要な処理内容**：
1. Rational{T}型の定義とコンストラクタ（自動約分付き）
2. `//` 演算子による有理数生成
3. 四則演算（+, -, *, /）
4. 比較演算（<, ==, <=）
5. 分子・分母取得（numerator, denominator）
6. 型変換と型昇格（convert, promote_rule）

**関連システム・外部連携**：整数演算（base/int.jl, base/intfuncs.jl のgcd）、型昇格システム（base/promotion.jl）と連携する。

**権限による制御**：特になし。すべてのユーザーが利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 有理数演算は画面に直接関連しないが、REPL上で `num//den` 形式で表示される |

## 機能種別

計算処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| num | T<:Integer | Yes | 分子 | 整数型であること |
| den | T<:Integer | Yes | 分母 | 整数型であること、ゼロの場合は分子もゼロでないこと |

### 入力データソース

`//` 演算子またはRational()コンストラクタ呼び出しとして直接渡される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 有理数 | Rational{T} | 約分済みの有理数 |
| 分子 | T | numerator(x)の結果 |
| 分母 | T | denominator(x)の結果 |

### 出力先

関数の戻り値として返される。

## 処理フロー

### 処理シーケンス

```
1. 入力の検証
   └─ 分子・分母が共にゼロの場合はArgumentError
2. 符号の正規化
   └─ 分母が負の場合、分子・分母の符号を反転
3. gcdによる約分
   └─ divgcd(num, den) で最大公約数で除算
4. Rational{T}オブジェクトの生成
   └─ unsafe_rational(T, num', den') で内部コンストラクタ呼び出し
```

### フローチャート

```mermaid
flowchart TD
    A["num // den 式"] --> B{num==0 && den==0?}
    B -->|Yes| C[ArgumentError]
    B -->|No| D{den < 0?}
    D -->|Yes| E[符号反転: num=-num, den=-den]
    D -->|No| F[そのまま]
    E --> G["divgcd(num, den)"]
    F --> G
    G --> H["Rational{T}(num', den')"]
    H --> I[約分済み有理数を返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 自動約分 | Rational構築時にgcdで自動的に約分される | Rational生成時 |
| BR-02 | 正規化 | 分母は常に正に正規化される | Rational生成時 |
| BR-03 | ゼロ/ゼロ禁止 | 分子・分母が共にゼロの場合はArgumentErrorを投げる | Rational生成時 |
| BR-04 | オーバーフロー検査 | 符号反転・乗算時にchecked_neg/checked_mulでオーバーフロー検査 | 演算時 |
| BR-05 | 浮動小数点不可 | `//` 演算子はAbstractFloat引数を受け付けない | //使用時 |
| BR-06 | 複素有理数 | Complex{<:Integer}型に対しても//演算子が使用可能 | 複素数//使用時 |

### 計算ロジック

- 約分: `divgcd(x, y) = (div(x, gcd(uabs(x), uabs(y))), div(y, gcd(uabs(x), uabs(y))))` （rational.jl 59-62行目）
- //演算子: `n // d = Rational(n, d)` （rational.jl 91行目）
- 有理数/整数: `x // y = divgcd(x.num, y) → checked_den(xn, checked_mul(x.den, yn))` （rational.jl 93-96行目）

## データベース操作仕様

### 操作別データベース影響一覧

該当なし（データベースを使用しない）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ArgumentError | ArgumentError | 0//0の生成 | ゼロ除算を回避する |
| OverflowError | OverflowError | checked_mul/checked_negでのオーバーフロー | BigIntを使用する |
| InexactError | InexactError | Unsigned型で負の結果が生じる場合 | Signed型を使用する |
| MethodError | MethodError | AbstractFloat引数で//を使用した場合 | 整数またはRational引数を使用する |

### リトライ仕様

有理数演算は純粋関数であり、リトライは適用されない。

## トランザクション仕様

該当なし。

## パフォーマンス要件

- gcd計算にSteinのバイナリアルゴリズムが使用され、Int64で約1.7倍高速
- checked演算のオーバーヘッドは通常の演算に比べて若干大きい
- 大きな分子・分母を持つRationalは演算ごとにgcdを計算するため、繰り返し演算でコストが蓄積する

## セキュリティ考慮事項

- 大量のRational演算で分子・分母が巨大になる「分数爆発」に注意（メモリ枯渇の可能性）
- 信頼できない入力からのRational生成はBigInt版を推奨

## 備考

- rational.jlの9-15行目で `struct Rational{T<:Integer} <: Real` が定義されている
- rational.jlの14行目で `unsafe_rational` が内部コンストラクタとして定義されている
- rational.jlの91行目で `//` 演算子が `Rational(n, d)` に委譲される

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

Rational型の内部構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | rational.jl | `base/rational.jl` | **9-15行目**: `struct Rational{T<:Integer} <: Real` 定義。num::Tとden::Tの2フィールド |
| 1-2 | rational.jl | `base/rational.jl` | **14行目**: `unsafe_rational` - チェックをバイパスする内部コンストラクタ |
| 1-3 | rational.jl | `base/rational.jl` | **17-18行目**: `unsafe_rational` の外部コンストラクタ（型推論用） |

**読解のコツ**: Rational{T}はReal型のサブタイプであり、数値型として通常の算術演算に参加できる。`unsafe_rational` は約分・符号正規化をスキップする高速コンストラクタで、内部使用向け。公開APIの `Rational(n, d)` や `//` は常に約分・検証を行う。

#### Step 2: エントリーポイントを理解する

Rationalの構築と//演算子を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | rational.jl | `base/rational.jl` | **20-26行目**: `checked_den` - 分母の符号正規化（checked_neg使用） |
| 2-2 | rational.jl | `base/rational.jl` | **31-46行目**: `Rational{T}(num, den)` - メインコンストラクタ。ゼロチェック、Unsigned対応、divgcd約分 |
| 2-3 | rational.jl | `base/rational.jl` | **52-62行目**: `divgcd` 関数 - gcdで分子・分母を約分 |
| 2-4 | rational.jl | `base/rational.jl` | **91行目**: `//(n::Integer, d::Integer) = Rational(n, d)` - //演算子 |

**主要処理フロー**:
1. **30行目**: `__throw_rational_argerror_zero(T)` - 0//0のエラーヘルパー
2. **32行目**: `iszero(den) && iszero(num)` - 0//0チェック
3. **33-41行目**: Unsigned型の特殊処理（負の結果はInexactError）
4. **43-44行目**: Signed型の処理（divgcd → checked_den）
5. **59-62行目**: `divgcd(x, y)` - `gcd(uabs(x), uabs(y))` で最大公約数を計算し除算

#### Step 3: //演算子の各種オーバーロードを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | rational.jl | `base/rational.jl` | **93-105行目**: Rational/Integer, Integer/Rational, Rational/Rational の//演算子 |
| 3-2 | rational.jl | `base/rational.jl` | **107-143行目**: Complex数対応の//演算子 |

#### Step 4: 表示関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | rational.jl | `base/rational.jl` | **147行目以降**: show関数 - `num//den` 形式での表示 |

### プログラム呼び出し階層図

```
// 演算子 (rational.jl:91)
    │
    └─ Rational(n, d) (rational.jl:48-49)
           │
           └─ Rational{T}(num, den) (rational.jl:31-46)
                  │
                  ├─ iszero(den) && iszero(num) → ArgumentError
                  │
                  ├─ divgcd(num, den) (rational.jl:59-62)
                  │      └─ gcd(uabs(x), uabs(y)) (intfuncs.jl:44-95)
                  │             └─ _gcd() Steinのバイナリアルゴリズム
                  │
                  ├─ checked_den(T, num', den') (rational.jl:20-26)
                  │      ├─ checked_neg (分母が負の場合)
                  │      └─ unsafe_rational(T, num', den')
                  │
                  └─ unsafe_rational(T, num, den) (rational.jl:14)
                         └─ new{T}(num, den)
```

### データフロー図

```
[入力]                        [処理]                          [出力]

n::Integer, d::Integer  ───▶ ゼロチェック               ───▶ ArgumentError (0//0)
                              │
                              ▼
                        ───▶ divgcd(n, d)               ───▶ (n', d') 約分済み
                              │    └─ gcd(|n|, |d|)
                              ▼
                        ───▶ checked_den(n', d')        ───▶ 符号正規化済み
                              │    └─ d'<0 → 符号反転
                              ▼
                        ───▶ unsafe_rational(T, n', d') ───▶ Rational{T}(n', d')
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| rational.jl | `base/rational.jl` | ソース | Rational型定義、//演算子、四則演算、show関数 |
| intfuncs.jl | `base/intfuncs.jl` | ソース | gcd関数（約分に使用） |
| int.jl | `base/int.jl` | ソース | 整数演算基盤 |
| checked.jl | `base/checked.jl` | ソース | checked_neg, checked_mul（オーバーフロー検出） |
| promotion.jl | `base/promotion.jl` | ソース | 型昇格基盤 |
