- 締切済み
100桁の計算ができなくて困っています
100桁の整数を2つ入力して和と積を求めたいのですが、プログラムが正常に動きません。 C言語を学び初めて数ヶ月しかたっていないので、力不足ということもありますが・・・ よろしくお願いします。
- みんなの回答 (9)
- 専門家の回答
みんなの回答
- Oh-Orange
- ベストアンサー率63% (854/1345)
★参考になりましたか? ・加算だけサンプルを載せておきます。 加算、減算は下位の桁から順番に処理していきます。 乗算は小学校で習った筆算の方法を思い出して実装します。 除算も小学校で習った筆算の方法で行えますが、アルゴリズムを しっかり整理しないと難解です。 ・下の『参考URL』もどうぞ。 サンプル: #define MAX_NUM1 (25) // 加減算用(100桁) #define MAX_NUM2 (50) // 乗除算用(200桁) #define BASE_VALUE (10000) // 1要素4桁なので10000進法 // 絶対値で加算 abc& abc:add( abc& a, abc& b ) { int carry = 0; // 加算 for ( int i = 0 ; i < MAX_NUM1 ; i++ ){ if ( (m_num[i] = (a.m_num[i] + b.m_num[i] + carry)) >= BASE_VALUE ){ m_num[ i ] -= BASE_VALUE; carry = 1; } else{ carry = 0; } } // キャリー(オーバーフロー) m_num[ i ] = carry; // 長さの補正 while ( --i >= 0 ){ if ( m_num[i] != 0 ){ m_len = (i + 1); return *this; } } m_len = 0; m_sin = 0; return *this; } 以上。
- Oh-Orange
- ベストアンサー率63% (854/1345)
★アドバイス >これを100桁まで入力して計算したいのですが、今の私の能力では難しくて・・・。 ↑ このままでは無理です。 int型が32ビットならば最大値が2,147,483,647ですので9桁です。 100桁までは計算できません。 >たぶん根本的に違うとは思いますが、もしソースを教えてもらえたら幸いです。 ↑ 分かっているようですね。 多倍長整数演算をご自分で組んで解決して下さい。 ソースは前回の『参考URL』で紹介しています。 これを参考に100桁まで計算できるように出来ますよ。 ・ちなみに多倍長演算するとき、乗算などは2倍の桁数が必要になります。 つまり100桁×100桁=200桁が必要になり、計算後100桁に丸めるか、オーバーフローとします。 あと入力に cin を使うのなら文字列でバッファに読み込み、文字列から多倍長整数の 構造体か、クラスにセットする仕組みをとります。あるいは使いやすいように cin の 『>>』演算子をオーバーロードします。 簡単なサンプル: class abc { int m_sin; int m_len; int m_num[ 50 + 1 ]; // 1要素4桁×50個=200桁(乗算用に2倍にしておく) public: abc(); abc& add( abc& a, abc& b ); // 加算 abc& sub( abc& a, abc& b ); // 減算 abc& mul( abc& a, abc& b ); // 乗算 abc& div( abc& a, abc& b, abc& r ); // 除算&剰余 }; 意味: m_sin…符号情報(-1=負数、0=ゼロ、+1=正数) m_len…有効な要素数 m_num[0]…最下位の要素 m_num[24]…最上位の要素 m_num[25]…オーバーフロー用の要素 数 -1234567890 は次のようにセットします。 m_num[0]=7890 m_num[1]=3456 m_num[2]=12 m_len=3 m_sin=-1 このような感じでクラスを設計して多倍長整数演算を作り上げてみて下さい。 以上。
- Oh-Orange
- ベストアンサー率63% (854/1345)
★アドバイス >100桁の整数を2つ入力して和と積を求めたいのですが、プログラムが正常に動きません。 ↑ ソースコードの一部でも載せてくれないとアドバイスできませんよ。 >C言語を学び初めて数ヶ月しかたっていないので、力不足ということもありますが・・・ >よろしくお願いします。 ↑ 『何』をよろしくとお願いしているのでしょうか? ソースを教えて欲しいのでしょうか? それならば次のリンクを参考にしてみて下さい。 http://homepage2.nifty.com/DSS/PT/HTML/Win/BCDCalc.htm→『BCD演算』 >100桁の整数を入力するときに、cin を使って入力したいのですが、それは可能ですか? ↑ cin で直接は無理でしょうね。 それから cin は C++ 言語です。 C言語にはありませんよ。 >また、できるだけ関数を使わずに作成したいと思います。 ↑ 単純に関数にしなければ良いです。 それだけですよ。 ・まずは上手く動作しないソースコードを補足に貼り付けて下さい。
補足
すいませんC++の間違いです。 このような非常に簡単なソースコードです。これを100桁まで入力して計算したいのですが、今の私の能力では難しくて・・・。 たぶん根本的に違うとは思いますが、もしソースを教えてもらえたら幸いです。 #include <iostream.h> main() { int x, y, wa,seki ; //入力 cout << "2つの整数を入力して下さい" << endl ; cin >> x >> y ; //計算 wa = x + y ; seki = x * y ; // 結果の表示 cout << x << " + " << y << " = " << wa << endl ; cout << x << " × " << y << " = " << seki << endl ; return 0; }
No5です。 申し訳ない、Cとしての「推敲」がしてなくて・・・。 全く同じ部分が3カ所も・・・。 以下のとおり共通部分を関数にしました。 下の関数を main 関数の前(プロトタイプ)に置き、 iKuriage = toString( cC, i, iKuriage ); の関数呼び出しを、該当3カ所と置き換えて下さい。 【関数】 int toString( char cC[], int i, int iKuriage ) { cC[i] += iKuriage; iKuriage = cC[i] / 10; cC[i] %= 10; cC[i] += 0x30; // 配列の値は、戻っても有効 return( iKuriage ); } (落ち着いて投稿すればいいのに・・) というか、ご質問の主旨が、No5 で記した 「★CPUのレジスタのサイズを超えての《計算方法(アルゴリズム)》というかプログラムは、ということ」 と思いこんでの投稿で・・、的をハズしてたらごめんなさい。
お礼
2度もご丁寧にありがとうございます。 皆様の指摘もあり、私が説明不足だったと実感しました。 もうひとつ質問したいことがあります。100桁の整数を入力するときに、cin を使って入力したいのですが、それは可能ですか?また、できるだけ関数を使わずに作成したいと思います。 参考プログラムまで載せていただいたのに、質問の追加をして本当に申し訳ありません・・・。
>100桁の整数を2つ入力して和と積を求めたい・・ 《計算結果》はどうでもよく、 ★CPUのレジスタのサイズを超えての《計算方法(アルゴリズム)》というかプログラムは、ということですね。 暇な年寄りは、50年近く前に算数で習ったとおり(*)に、★「足し算」について、以下のとおりプログラムしてみました(サンプル「数」は100桁ないけど・・)。 なお、「かけ算」も、各桁の積を配列に入れ、桁上げ(MAX:9X9=81、char型範囲内)処理すれば簡単かと・・・これは自分で。 (*)下の位から桁上げを忘れずに・・・(な~んだ簡単)。 ☆円周率も、習ったとおりの「割り算」方法(「余り」をずっと割っていく)で何桁も求めることが出来ます(割り算の形にするのにちょっと、勉強が必要だけど・・・)。 ★文字コード(数≠数字)など、参考になれば、と思います。 #include <stdio.h> #include <string.h> void main() { int i, iLenA, iLenB, iKuriage = 0; char cA[128] = "12345678912345678946687123115654"; char cB[128] = "987654321987654321987654321025878997"; char cC[128]; // 8の倍数で確保(趣味の世界?) for( i = 0; i < 128; i++ ) cC[i] = 0x00; // 初期化 iLenA = strlen( cA ); iLenB = strlen( cB ); for( i = 99; i >= 0; i-- ){ // 100桁 iLenA--; // 下の位から iLenB--; if( iLenA >= 0 ){ if( iLenB >= 0 ){ cC[i] = cA[iLenA] - 0x30; cC[i] += cB[iLenB] - 0x30; cC[i] += iKuriage; iKuriage = cC[i] / 10; cC[i] %= 10; cC[i] += 0x30; } if( iLenB < 0 ){ cC[i] = cA[iLenA] - 0x30; cC[i] += iKuriage; iKuriage = cC[i] / 10; cC[i] %= 10; cC[i] += 0x30; } continue; } if( iLenB >= 0 ){ cC[i] = cB[iLenB] - 0x30; cC[i] += iKuriage; iKuriage = cC[i] / 10; cC[i] %= 10; cC[i] += 0x30; continue; } break; } printf( " %40s\n", cA ); // 例)40桁以内 printf( "+%40s\n", cB ); printf( "=%40s\n", &cC[i+1] ); } 注:タブの代わりに全角空白を用いています。
C言語で用意されているint型はせいぜい数桁までしか計算できません。 確かunsigned long longなどでも十数桁が限度だったと思います。 今後64ビットマシンに移行して扱える桁が増えるとかいう話もあるみたいですが。 そもそも8桁でさえ1億ですよ? 100桁の数値を扱いたいならそれ用のライブラリ(個人製作などの)を 探して使うか、PS3のセルのように変数を分割して個々に値を 容量単位で保存させてフラグを倒したり起こしたりして・・・など ちょっとした計算機を作るような手間暇かけて自作するしかありません。 当然それなりの経験者ならメモリ管理やSTLを駆使すればできなくは無いのですが、 Cの学び始めでそれをやるのはさすがに難しいでしょう。 そもそもなぜ100桁をやろうと思ったのですか? それを教えていただけたらそれをしなくても済む解決策を誰かが教えてくれる かもしれませんよ。
- tak0san
- ベストアンサー率35% (14/39)
みなさん言っているように100桁の和と積は組み込み整数型(longなど) では計算できません。 多倍長演算ライブラリを作るなり、利用する必要があるでしょう。 C言語でなくてもよいのであれば、Rubyならとくに考えずに計算できます。
- koko_u_
- ベストアンサー率18% (459/2509)
まさか組み込み型(long int など)で計算しようとしたりはしてませんよね。 というか「プログラムが正常に動きません。」だけでアドバイスなど不可能なんですが。
- redfox63
- ベストアンサー率71% (1325/1856)
どのようなコードをお書きになっているのかを補足してください 100桁同士の掛け算の結果は10,000桁になるのですがこの点ご理解なさっていますか char型の配列を用意して各桁に1要素割り当てて下のから演算かな・・・
お礼
参考になりました。 ご丁寧にありがとうございました。