2011年12月31日土曜日

大きな桁数の足し算

最近生活リズムが乱れまくってますね…

ニートなんてこんなもんです(キリッ

ごめんなさい...


とりあえず 大きな数値同士の足し算をする関数
第一引数に最初の数値を
第二引数に次の数値を
第三引数に結果を
戻り値に結果の桁数を
という感じ
ムダな処理とかもかなりあるけど
PCで動作確認だけする予定だったので
移植性とか全く考えてないんですよ…
だってPICで1000桁同士の足し算とかやらないじゃないですか…

とりあえず「結果の桁数がintに収まる程度」までは計算できると思います
(実際問題として配列とかの最大数の問題があるので intの最大数までの計算はできませんが)

引数はすべて文字列へのポインタです
最低限の条件として
第一引数長 < 第三引数長 && 第二引数長 < 第三引数長
である必要があります

処理としては
文字列長獲得

文字列前後反転

文字列から数字を抜き出して足し算

文字列前後反転
という感じです

戻り値がintなので
例えば文字列の中に数字以外が含まれていたらEOFを返して終了
とかにしてもいいかも

このコードはけっこームダが多い気がするので
実際には使わないが吉と思いますけど
一応書いておきます
デカイ数字を扱うのにこういう方法もあるんだよ~
という一例として


int add(char *text1, char *text2, char *text3) {

char
*text1p, *text1q, *text1c,
*text2p, *text2q, *text2c,
*text3p, *text3q,
ca, cal = 0;
int i;

for ( text1p = text1; *text1p != '\0'; text1p++ ) ;
for ( text2p = text2; *text2p != '\0'; text2p++ ) ;

text1c = text1p;
text2c = text2p;

*(text1p--) = '\0';
*(text2p--) = '\0';

for ( text1q = text1; text1p > text1q; ) {
ca = *text1p;
*text1p = *text1q;
*text1q = ca;
text1p--;
text1q++;
}

for ( text2q = text2; text2p > text2q; ) {
ca = *text2p;
*text2p = *text2q;
*text2q = ca;
text2p--;
text2q++;
}

for ( i = 0; ; i++ ) {
if ((text1 + i) >= text1c && (text2 + i) >= text2c && !cal) {
*(text3 + i) = '\0';
break;
}
*(text3 + i) = (
((text1 + i < text1c) ? (*(text1 + i)) - '0' : 0) +
((text2 + i < text2c) ? (*(text2 + i)) - '0' : 0) +
cal);
if (*(text3 + i) >= 10) {
*(text3 + i) -= 10;
cal = 1;
} else {
cal = 0;
}
*(text3 + i) += '0';
}
text3p = text3 + i - 1;
text3q = text3;

while (text3p > text3q) {
ca = *text3p;
*text3p = *text3q;
*text3q = ca;
text3p--;
text3q++;
}

return i;
}


とりあえず
この程度の桁数なら「数世代前」のPCでも一瞬で計算できます
まぁ… あたりまえっちゃー当たり前なんですが
PCはC2Q RAM8G Win7Ux64

※画像はCで作った「コマンドライン引数で与えられた数値を足してstdiutに出力する」というコンソールアプリをC#で呼び出してGUIにしているものです


お世辞にも綺麗と言えるコードではないですけど
AOJでトップランククラスのコードだとどういう風に扱ってるんでしょ
まずテキストで扱うということはしてないと思うのですけども…


↑のコードは上記PCでVisual C++ 2010を使って作成したものです
またGUI部分はVisual C# 2010で作成しました



/* 今年最後の1日は「彼女はつっこまれるのが好き!5」を読みながら開始しました
  どんな一日になるんだろう
  とりあえず宇宙へのパスポートを読みながら寝ようかと思いつつ */

0 件のコメント:

コメントを投稿