プログラミング
 Computer >> コンピューター >  >> プログラミング >> プログラミング

n進数同士の加算アルゴリズムをC++で実装する方法

問題の概要

この問題では、基数(底)が n である2つの数が与えられます。これらの数を加算し、その結果も同じく n進法で求めることが目的です。

基本的な解き方の流れは以下のとおりです。まず与えられた2つの数をそれぞれ10進数に変換します。10進数に変換できれば、あとは通常の整数演算で簡単に加算できます。最後に、加算結果を再び n進数へ変換して出力します。

ここで注意すべき点は、n進数を文字列として扱うことです。基数が9を超える場合、10以上の値を1桁で表すためにアルファベットを使う必要があるからです。たとえば16進数では、10〜15を表すのに A〜F の6文字が使用されます。

入力と出力の例

入力:
基数:16
1つ目の数:2C
2つ目の数:5F

出力:
加算結果:8B

アルゴリズム

baseNtoDec(number, base) ― n進数を10進数へ変換

入力:n進数の数値文字列と基数 n の値
出力:10進数に変換した値

Begin
    len := number の桁数
    power := 1
    num := 0

    for i := len-1 down to 0, do
        if number[i] >= base, then
            return 不正な数値
        num := num + number[i] * power
        power := power * base
    done

    return num
End

最下位桁から順に、各桁の値に基数のべき乗を掛けながら累積することで、n進数を10進数へ変換します。ある桁の値が基数以上であれば、それは有効な数ではないためエラーを返します。

decToBaseN(dec, base) ― 10進数をn進数へ変換

入力:10進数と、変換先の基数 n
出力:n進数の数値文字列

Begin
    while dec > 0, do
        res := (dec mod base) を res に連結
        dec := dec / base
    done

    res を反転する
    return res
End

10進数を基数で割った余りを順に取り出していくことで n進数を得られます。余りは下位桁から求まるため、最後に文字列を反転させて正しい桁順に整えます。

addBaseN(num1, num2, base) ― n進数の加算

入力:n進数で表された2つの数と基数 n
出力:n進法で加算した結果

Begin
    dec1 := baseNtoDec(num1, base)
    dec2 := baseNtoDec(num2, base)
    sum := decToBaseN(dec1 + dec2, base)
    return sum
End

C++による実装例

#include<iostream>
#include<algorithm>
using namespace std;

int getVal(char c) {
    if(c >= '0' && c<='9')
        return int(c-'0');      // 数字の10進数としての値を返す
    else
        return int(c-'A'+10);   // 英字(A〜F)は10以上の値に対応させる
}

char revVal(int n) {
    if(n >= 0 && n <=9)
        return char(n+'0');     // 数値に対応する文字を返す
    else
        return char(n+'A'-10);  // 10以上の数値に対応する英字を返す
}

int baseNtoDec(string number, int base) {
    int len = number.size();
    int power = 1;
    int num = 0;

    for(int i = len-1; i>= 0; i--) {   // 最下位桁から最上位桁へ処理
        if(getVal(number[i]) >= base)
            return INT_MIN;            // 桁の値が基数以上ならエラーとして負の極小値を返す
        num += getVal(number[i])*power;
        power = power*base;
    }
    return num;
}

string decToBaseN(int dec, int base) {
    string res = "";            // 空文字列で初期化
    while(dec > 0) {
        res += revVal(dec%base);
        dec /= base;
    }

    reverse(res.begin(), res.end());   // 反転して正しい桁順にする
    return res;
}

int main() {
    int base;
    string num1, num2, sum;
    cout << "Enter Base: "; cin >> base;
    cout << "Enter first number in base "<<base<<": ";cin >> num1;
    cout << "Enter second number in base "<<base<<": ";cin >> num2;
    sum = decToBaseN((baseNtoDec(num1, base) + baseNtoDec(num2, base)), base);
    cout << "The result of addition is: " << sum;
}

実行結果

Enter Base: 16
Enter first number in base 16: 2C
Enter second number in base 16: 5F
The result of addition is: 8B

処理のポイント

このプログラムでは、getVal 関数が文字を対応する数値へ変換し、revVal 関数がその逆(数値から文字への変換)を担っています。これにより、16進数のように英字を含む基数にも柔軟に対応できます。

また、baseNtoDec では各桁の値が基数未満であるかどうかをチェックし、不正な入力に対しては INT_MIN を返してエラーを通知します。decToBaseN は「割り算の余り」を繰り返し取り出すことで10進数を任意の基数へ変換しており、この一連の変換処理こそが本プログラムの中核となる仕組みです。

  1. JavaScriptの数値(Number)の基本と実践サンプルコード

    JavaScriptでは、整数も小数もすべて「Number」型として扱われます。この記事では、数値変数の定義方法と、それらを使った簡単な演算の例を、動作するHTMLサンプルコードとともに紹介します。サンプルコード以下は、JavaScriptで数値を扱う基本的な例です。整数(22、99)と小数(1.523)を変数に格納し、ボタンをクリックすると画面に表示する仕組みになっています。<!DOCTYPE html> <html lang=ja> <head> <meta charset=UTF-8 /> <meta name=viewport co

  2. JavaScriptで2つの数値を加算する際に必要な繰り上がり(キャリー)の回数を求める方法

    問題 2つの数値を受け取るJavaScriptの関数を記述する必要があります。 この関数は、まるで紙の上で筆算を行うように、その2つの数値を加算する際に発生する繰り上がり(キャリー)の回数を数えて返すものとします。 例えば、次の図のように 179 と 284 を足し合わせる場合、繰り上がりは2回発生します。したがって、この2つの数値を渡したとき、関数は 2 を返す必要があります。 解き方のポイント この問題は、各桁を下の位から順番に見ていき、「その桁の2つの数字と、前の桁からの繰り上がりの合計が10以上になったかどうか」を判定することで解けます。 剰余演算子(%)を使えば、数値の一番下の