[C言語] 最大公約数を求めるプログラムの書き方

C言語で最大公約数を求めるには、ユークリッドの互除法を用いるのが一般的です。

この方法では、2つの整数のうち大きい方を小さい方で割り、その余りで再び割り算を行う操作を繰り返します。

余りが0になった時の除数が最大公約数となります。

このアルゴリズムは、再帰関数やループを用いて実装することができます。

例えば、関数名をgcdとし、引数に2つの整数を取るように設計します。

この方法は効率的で、計算量が少ないため、広く利用されています。

この記事でわかること
  • ユークリッドの互除法の基本的なアルゴリズム
  • C言語での最大公約数の実装方法(再帰とループ)
  • 複数の数値の最大公約数を求める方法
  • 最大公約数を用いた分数の約分の方法
  • 最大公約数を用いた整数の組み合わせ問題の解決方法

目次から探す

ユークリッドの互除法

ユークリッドの互除法の概要

ユークリッドの互除法は、2つの整数の最大公約数(GCD: Greatest Common Divisor)を効率的に求めるための古典的なアルゴリズムです。

この方法は、紀元前300年頃にユークリッドによって記述されたとされ、現在でも広く使用されています。

互除法は、2つの数のうち小さい方の数で大きい方の数を割り、その余りを次の計算に用いるという手順を繰り返すことで、最大公約数を求めます。

アルゴリズムの説明

ユークリッドの互除法のアルゴリズムは以下の手順で進行します。

  1. 2つの整数 (a) と (b) を用意します(ここで (a > b) と仮定します)。
  2. (a) を (b) で割り、余り (r) を求めます。
  3. 余り (r) が0でない場合、(a) を (b) に、(b) を (r) に置き換え、手順2に戻ります。
  4. 余り (r) が0になったとき、(b) が最大公約数です。

このアルゴリズムは、余りが0になるまで繰り返され、最終的に最大公約数が得られます。

手計算による例

具体的な例として、48と18の最大公約数を求めてみましょう。

  1. 48を18で割ります。

商は2、余りは12です。

  • 計算: (48 / 18 = 2) 余り (12)
  1. 次に、18を12で割ります。

商は1、余りは6です。

  • 計算: (18 / 12 = 1) 余り (6)
  1. 次に、12を6で割ります。

商は2、余りは0です。

  • 計算: (12 / 6 = 2) 余り (0)

余りが0になったので、最後に割った数6が48と18の最大公約数です。

このように、ユークリッドの互除法を用いることで、手計算でも簡単に最大公約数を求めることができます。

C言語での実装方法

必要なヘッダファイル

C言語でプログラムを作成する際には、標準入出力を扱うためにstdio.hをインクルードする必要があります。

これにより、printfscanfといった関数を使用することができます。

#include <stdio.h>

関数のプロトタイプ宣言

関数のプロトタイプ宣言は、関数の定義を行う前に、その関数の名前、引数の型、戻り値の型を宣言するものです。

これにより、コンパイラは関数の使用を認識し、正しい引数の型や戻り値の型をチェックすることができます。

int gcd(int a, int b);

ユークリッドの互除法を用いた実装

ユークリッドの互除法を用いた最大公約数の計算をC言語で実装する方法を示します。

ここでは、再帰を用いた方法とループを用いた方法の2つを紹介します。

再帰を用いた実装

再帰を用いると、関数が自分自身を呼び出すことで問題を解決します。

以下は、再帰を用いたユークリッドの互除法の実装例です。

#include <stdio.h>
// 最大公約数を求める再帰関数
int gcd(int a, int b) {
    if (b == 0) {
        return a;
    } else {
        return gcd(b, a % b);
    }
}
int main() {
    int num1 = 48, num2 = 18;
    printf("最大公約数: %d\n", gcd(num1, num2));
    return 0;
}
最大公約数: 6

このプログラムは、48と18の最大公約数を再帰的に求め、結果を出力します。

ループを用いた実装

ループを用いると、再帰を使わずに繰り返し処理を行うことができます。

以下は、ループを用いたユークリッドの互除法の実装例です。

#include <stdio.h>
// 最大公約数を求めるループ関数
int gcd(int a, int b) {
    while (b != 0) {
        int temp = b;
        b = a % b;
        a = temp;
    }
    return a;
}
int main() {
    int num1 = 48, num2 = 18;
    printf("最大公約数: %d\n", gcd(num1, num2));
    return 0;
}
最大公約数: 6

このプログラムは、ループを用いて48と18の最大公約数を求め、結果を出力します。

再帰を使わないため、スタックオーバーフローの心配がなく、より大きな数値にも対応しやすいです。

完成したプログラム

ここでは、ユークリッドの互除法を用いて最大公約数を求めるC言語のプログラムを完成形として紹介します。

このプログラムは、ユーザーから2つの整数を入力として受け取り、それらの最大公約数を計算して出力します。

再帰を用いた方法とループを用いた方法の両方を含めています。

#include <stdio.h>
// 再帰を用いた最大公約数を求める関数
int gcd_recursive(int a, int b) {
    if (b == 0) {
        return a;
    } else {
        return gcd_recursive(b, a % b);
    }
}
// ループを用いた最大公約数を求める関数
int gcd_loop(int a, int b) {
    while (b != 0) {
        int temp = b;
        b = a % b;
        a = temp;
    }
    return a;
}
int main() {
    int num1, num2;
    // ユーザーからの入力を受け取る
    printf("2つの整数を入力してください: ");
    scanf("%d %d", &num1, &num2);
    // 再帰を用いた方法で最大公約数を計算
    int result_recursive = gcd_recursive(num1, num2);
    printf("再帰を用いた最大公約数: %d\n", result_recursive);
    // ループを用いた方法で最大公約数を計算
    int result_loop = gcd_loop(num1, num2);
    printf("ループを用いた最大公約数: %d\n", result_loop);
    return 0;
}
2つの整数を入力してください: 48 18
再帰を用いた最大公約数: 6
ループを用いた最大公約数: 6

このプログラムは、ユーザーが入力した2つの整数の最大公約数を、再帰とループの両方の方法で計算し、それぞれの結果を出力します。

どちらの方法でも同じ結果が得られることを確認できます。

再帰を用いるとコードが簡潔になりますが、ループを用いるとスタックオーバーフローのリスクがなく、より大きな数値にも対応しやすいという利点があります。

応用例

複数の数値の最大公約数を求める

複数の数値の最大公約数を求めるには、2つの数値の最大公約数を順次計算していく方法が有効です。

例えば、3つの数値 (a), (b), (c) の最大公約数を求める場合、まず (a) と (b) の最大公約数を求め、その結果と (c) の最大公約数を求めるという手順を取ります。

#include <stdio.h>
// 最大公約数を求める関数
int gcd(int a, int b) {
    while (b != 0) {
        int temp = b;
        b = a % b;
        a = temp;
    }
    return a;
}
// 複数の数値の最大公約数を求める関数
int gcd_multiple(int numbers[], int count) {
    int result = numbers[0];
    for (int i = 1; i < count; i++) {
        result = gcd(result, numbers[i]);
    }
    return result;
}
int main() {
    int numbers[] = {48, 18, 30};
    int count = sizeof(numbers) / sizeof(numbers[0]);
    printf("複数の数値の最大公約数: %d\n", gcd_multiple(numbers, count));
    return 0;
}
複数の数値の最大公約数: 6

このプログラムは、配列に格納された複数の整数の最大公約数を求めます。

最大公約数を用いた分数の約分

最大公約数を用いることで、分数を簡単に約分することができます。

分子と分母の最大公約数を求め、その値で分子と分母を割ることで、約分された分数を得ることができます。

#include <stdio.h>
// 最大公約数を求める関数
int gcd(int a, int b) {
    while (b != 0) {
        int temp = b;
        b = a % b;
        a = temp;
    }
    return a;
}
// 分数を約分する関数
void reduce_fraction(int *numerator, int *denominator) {
    int gcd_value = gcd(*numerator, *denominator);
    *numerator /= gcd_value;
    *denominator /= gcd_value;
}
int main() {
    int numerator = 48, denominator = 18;
    reduce_fraction(&numerator, &denominator);
    printf("約分された分数: %d/%d\n", numerator, denominator);
    return 0;
}
約分された分数: 8/3

このプログラムは、分子48と分母18の分数を約分し、結果を出力します。

最大公約数を用いた整数の組み合わせ問題

最大公約数は、整数の組み合わせ問題にも応用できます。

例えば、ある数の組み合わせで特定の数を作ることができるかどうかを判断する際に、最大公約数を用いることができます。

2つの数の最大公約数が1であれば、それらの数の任意の整数倍の組み合わせで任意の整数を作ることが可能です。

#include <stdio.h>
// 最大公約数を求める関数
int gcd(int a, int b) {
    while (b != 0) {
        int temp = b;
        b = a % b;
        a = temp;
    }
    return a;
}
// 組み合わせ可能かどうかを判定する関数
int can_combine(int a, int b, int target) {
    return target % gcd(a, b) == 0;
}
int main() {
    int a = 3, b = 5, target = 11;
    if (can_combine(a, b, target)) {
        printf("%dと%dの組み合わせで%dを作ることができます。\n", a, b, target);
    } else {
        printf("%dと%dの組み合わせで%dを作ることはできません。\n", a, b, target);
    }
    return 0;
}
3と5の組み合わせで11を作ることができます。

このプログラムは、3と5の整数の組み合わせで11を作ることが可能かどうかを判定し、結果を出力します。

よくある質問

最大公約数と最小公倍数の違いは?

最大公約数(GCD)は、2つ以上の整数に共通する最大の正の整数です。

一方、最小公倍数(LCM)は、2つ以上の整数の倍数の中で最小の正の整数です。

例えば、12と18の最大公約数は6であり、最小公倍数は36です。

最大公約数は整数を分割する際に、最小公倍数は整数を組み合わせる際に役立ちます。

再帰とループ、どちらが効率的?

再帰とループのどちらが効率的かは、具体的な状況によります。

再帰はコードを簡潔にし、理解しやすくすることができますが、深い再帰呼び出しはスタックオーバーフローを引き起こす可能性があります。

ループはスタックを使用しないため、メモリ効率が良く、特に大きなデータセットに対してはループの方が適している場合があります。

例:forループを使う。

負の数を扱う場合はどうする?

負の数を扱う場合、最大公約数の計算においては、通常、絶対値を使用します。

これは、最大公約数が正の整数であるためです。

したがって、負の数が入力された場合は、まずその絶対値を取ってから計算を行います。

例:abs(a)を使う。

まとめ

ユークリッドの互除法を用いた最大公約数の計算は、C言語での実装を通じて効率的に行うことができます。

再帰とループの両方の方法を理解し、応用例を通じて実際の問題にどのように適用できるかを学びました。

この記事を参考に、最大公約数を活用したプログラムを作成し、さらに複雑な問題に挑戦してみてください。

  • URLをコピーしました!
目次から探す