• ベストアンサー

最大50桁の実数の和・差・積を求めたい

C++で、2つの最大50桁の実数を入力して、その和・差・積を求めるプログラムを作りたいのです。 実数をchar型に入力させて、それを1桁ずつint型に変換したいのですが、どのようにやればよいのでしょうか? また、その際、符号や小数点はどうすればよいのでしょうか? 計算の流れとしては、 ○足し算 小数点を合わせる ⇒下位の桁から1桁ずつ足し算していく ⇒結果が10以上の場合、10を引き、左隣の桁の数字に1を加える ○引き算 小数点を合わせる ⇒下位の桁から1桁ずつ引き算していく ⇒引かれる数字のほうが引く数字より小さい場合、引かれる数字に10を足し、左隣の桁の引かれる数字から1を引く というような感じで考えているのですが、小数点の合わせ方がわかりません。 また、掛け算に関しては、筆算の要領でやろうと思うのですが、どのようにやればよいのでしょうか? 私はC++の勉強歴が短いので、できれば初心者向けのわかりやすい説明でお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • chie65535
  • ベストアンサー率43% (8533/19397)
回答No.7

>小数点の合わせ方がわかりません。 小数点は、別に持っておく方が良いでしょう。もちろん、正負の符号も別に持ちます。 例えば… data1[0]=1 data1[1]=2 data1[2]=3 data1[3]=4 data1[4]=5 data1[5]~data[49]=0 expnum1=5 //小数点の位置 signflag1=0 //0なら正 の時(小数点の位置が5、データが123450~(略)~0の時)には「12345」を意味します。 data1[0]=1 data1[1]=2 data1[2]=3 data1[3]=4 data1[4]=5 data1[5]~data[49]=0 expnum1=3 //小数点の位置 signflag1=0 //0なら正 の時(小数点の位置が5、データが123450~(略)~0の時)には「123.45」を意味します。 data1[0]=1 data1[1]=2 data1[2]=3 data1[3]=4 data1[4]=5 data1[5]~data[49]=0 expnum1=7 //小数点の位置 signflag1=0 //0なら正 の時(小数点の位置が7、データが123450~(略)~0の時)には「1234500」を意味します。 で、小数点を合わせて加減算をする時は、以下のようにします。 1.足される数と足す数、引かれる数と引く数で、小数点の位置が小さい方を「小数点の位置の差」だけ右にズラします。 例:12345+123.45の時 片方は小数点の位置5、もう片方は小数点の位置3だとすると「5-3=2」で、小数点の位置3の方を右に2桁ズラします。 小数点の位置5:12345000000000000000000000000000000000000000000000 + 小数点の位置3:12345000000000000000000000000000000000000000000000 ↓ 小数点の位置5:12345000000000000000000000000000000000000000000000 + 小数点の位置5:00123450000000000000000000000000000000000000000000 右に2桁ズラした方の値の、下位の2桁は、はみ出して消えます。 また、ズラして空いた上位の2桁には0を補います。 2.小数点の位置が揃ったので、両方を加減算します。 小数点の位置5:12345000000000000000000000000000000000000000000000 + 小数点の位置5:00123450000000000000000000000000000000000000000000 || 小数点の位置5:12468450000000000000000000000000000000000000000000 3-A.もし足し算で桁溢れした場合は、結果を右に1桁ズラして、溢れた数を最上位に入れ、小数点の位置も1つ増やします。 例:567.89+987.65 小数点の位置3:56789000000000000000000000000000000000000000000000 + 小数点の位置3:98765000000000000000000000000000000000000000000000 || 小数点の位置3:55554000000000000000000000000000000000000000000000 最上位の「5+9」で「1」が溢れた。 ↓ 小数点の位置4:05555400000000000000000000000000000000000000000000 1桁左にズラして、小数点の位置を1増やす。 ↓ 小数点の位置4:15555400000000000000000000000000000000000000000000 加算時に溢れた「1」を空いた最上位に入れる。 3-B.もし引き算で、最上位が0になった場合、結果を左に1桁ズラして、小数点の位置も1つ減らします。 例:1555.54-567.89 小数点の位置4:15555400000000000000000000000000000000000000000000 | 小数点の位置4:09876500000000000000000000000000000000000000000000 (前述の1の処理で、小数点の位置を合わせ済み) || 小数点の位置4:05678900000000000000000000000000000000000000000000 ↓ 小数点の位置3:56789000000000000000000000000000000000000000000000 左に1桁ズラして、小数点の位置を1つ減らす。 ここまでが「小数点の合わせ方」です。 なお、加減算を行う前に、両方の数の正と負を見ておいて、正負の符号を外して「正の数同士の足し算、引き算」にしましょう。 A(正)+B(正)⇒A(正)+B(正) A(正)+B(負)⇒A(正)-B(正) A(負)+B(正)⇒B(正)-A(正) A(負)+B(負)⇒-(A(正)+B(正)) A(正)-B(正)⇒A(正)-B(正) A(正)-B(負)⇒A(正)+B(正) A(負)-B(正)⇒A(負)+B(負)⇒-(A(正)+B(正)) A(負)-B(負)⇒A(負)+B(正)⇒B(正)-A(正) そして、引き算、足し算を変換して「A(正)-B(正)」や「B(正)-A(正)」になった場合に「小さい数-大きい数」の時は、更に「-(大きい数-小さい数)」に変換します。 例:(-10)-(-4)を計算する 規則 A(負)-B(負)⇒A(負)+B(正)⇒B(正)-A(正) により 4-10 に変換する。 規則 「小さい数-大きい数」の時は、「-(大きい数-小さい数)」に変換 により 10-4 で6を求めてから正負の符号を変え-6にする。 このようにすると「加算と減算は、正の数だけしか扱わない」ので、とても楽になります。引き算も常に「大きい数-小さい数」しか行わないので「上の桁から借りて来る」のも楽になります。

purogura2
質問者

お礼

とても丁寧な回答ありがとうございます。 例もつけていただいて、とても分かりやすかったです。 ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (8)

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.9

★アドバイス ・次の2つを参考にどうぞ。  http://homepage2.nifty.com/DSS/PT/HTML/Win/BCDCalc.htm→『BCD演算』  http://www.vector.co.jp/soft/win95/prog/se438696.html→『BCD演算ルーチン』  解説はありませんが直ぐにでも利用できそうです。  時間があったら仕組みをソースから読み取りましょう。

参考URL:
http://homepage2.nifty.com/DSS/PT/HTML/Win/BCDCalc.htm
全文を見る
すると、全ての回答が全文表示されます。
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.8

> C++をもっと勉強します。 今回の内容は、C++に限らない、プログラミング一般の問題でひっかかっているのですよね。だとすると、C++だけをいくら勉強しても解決にはいたりません。 紙と鉛筆で、どうやれば実現できるかを導けるようになって、はじめてC++固有の勉強が活きてきます。

全文を見る
すると、全ての回答が全文表示されます。
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.6

#1です。 > charの配列です。 なるほど。 それであれば、 int toint(char c) {  return std::isdigit(static_cast<unsigned char>(c)) ? c - '0' : c; } といった関数を作っておいて、 char s[53]; // ←の配列に入力 int a[50 + 2]; std::size_t n = std::strlen(s); std::transform(s + 0, s + n, a, &toint); とでもしておけばどうでしょう。 > また、その際、符号や小数点はどうすればよいのでしょうか? 決めてください。 上の例ではそのままにしています。 > できれば初心者向けのわかりやすい説明でお願いします。 C++はCと同じで、初心者お断りのプログラム言語です。 C++自体の経験が浅いのは仕方ありませんが、少なくとも初心者を自称しないだけの覚悟が出来てから取り組みましょう。

purogura2
質問者

お礼

回答ありがとうございます。 C++をもっと勉強します。

全文を見る
すると、全ての回答が全文表示されます。
  • zwi
  • ベストアンサー率56% (730/1282)
回答No.5

多倍長演算ですね。 下記サイトにソース公開されたライブラリがありますので、そのまま使われるか、勉強用の参考用としてお使いください。 http://www5.airnet.ne.jp/tomy/cpro/csource.htm >できれば初心者向けのわかりやすい説明でお願いします ともかく苦労しないとC++は覚えれませんので、悩みましょう。

purogura2
質問者

お礼

回答ありがとうございます。 紹介していただいたホームページ参考にしてみます。

全文を見る
すると、全ての回答が全文表示されます。
  • yama5140
  • ベストアンサー率54% (136/250)
回答No.4

>C++で、2つの最大50桁の実数を入力して、・・・  「丸投げ」?。  ひと月勉強して、それでも判らない場合、再度「丸投げ」したら如何でしょう。  http://service.okwave.jp/okwave/info/okwave/index.html#info_0216  ↑ここに、 >なお、「丸投げ・依頼」の改定につきましては、3月16日(月)12:00以降に・・  「丸投げ・依頼」が解禁されるようです。 -------------------------------------------------- 「削除」されてしまうので、聞いても無駄かもしれませんが・・2点。 >私はC++の勉強歴が短いので、できれば初心者向けのわかりやすい説明でお願いします。  ・「勉強歴が短い」のに、なぜこの「プログラムを作りたい」と思ったのですか?。  ・「わかりやすい」とは、質問者様の判断ですよね、それを回答する側が想像して答えろ・・ですか?。 「超初心者対象の」ホームページを紹介します。「ひと月」頑張ってみてください。   http://www.kumei.ne.jp/c_lang/

purogura2
質問者

補足

申し訳ありません。 確かに「丸投げ」のようなかたちになってしまいました。 紹介していただいたホームページを参考にしてみます。

全文を見る
すると、全ての回答が全文表示されます。
回答No.3

50桁だと、C/C++の標準型では処理できません。 つまり、整数(int long longlong __int64)等を 対象数値(50桁)の直接の演算には使用できません。 BCD演算ライブラリを使用するか、自分で BCDクラスを作って処理しましょう。 ちなみにBCDとは1Byteで0~9を表現して演算する方法です。 少数表現にはいろいろな方法が考えられますが、 1数値に対して多くて1つしか発生しませんので 1.少数点を意味する数値(0xF等)を入れる。 2.少数桁数を数値で付加しておく 等の方法などはどうでしょうか。 いずれにしても、初心者がいきなり挑戦すべき 課題ではありませんので、operatorのオーバーライドが できる程度になってから改めて挑戦しましょう。

purogura2
質問者

補足

実数をchar配列に入れて、それを1桁ずつint型に変換するというのはできないということでしょうか? BCDについて勉強してみます。

全文を見る
すると、全ての回答が全文表示されます。
  • titokani
  • ベストアンサー率19% (341/1726)
回答No.2

小数点以上を50桁、小数点以下も50桁とした固定小数点で扱う方法はどうでしょうか?

purogura2
質問者

お礼

なるほど。参考にします。 ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.1

> 実数をchar型に入力させて、それを1桁ずつint型に変換したいのですが、どのようにやればよいのでしょうか? char型が8ビットだとすると、10進法で2桁しか格納できないと思います。 charの配列ではないのですか? その場合、なぜstd::stringではいけないのですか?

purogura2
質問者

補足

> charの配列ではないのですか? すいません。そのとおりです。 charの配列です。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 新しい実数の構成:自然数→正の実数→実数

    次のような実数の構成はあるのでしょうか? まず、10進法の表記により自然数を構成します。 0を含めます。 0,1,2,3,4,5,6,7,8,9,10, 11、12、・・・ といった数を考えます。 ケタ数は有限です。 順序関係は、まず、ケタの大小を比べ、ケタが同じであれば、最大ケタの数字を比べます。 0~9までの加法と乗法を九九として決め、一般の自然数の加法と乗法は筆算により定めます。 つぎに、小数点以下を考えます。 まず、小数点以下のケタ数が有限なる数を考えても、順序関係と加法・乗法はいままでと同様です。 そして、小数点以下のケタ数が無限なる数を考えます。 順序関係はいままでに追加して、 1=1.000・・・=0.999・・・ といったことなどを考えます。 加法と乗法の筆算も、「左から計算」していけばいいと思います。 このとき、新しく除法も考えられます。 これで、正の実数が構成できたと思いますが、 最後に、小数点以上のケタ数が無限なる数を考えます。 たとえば、 ・・・1212.12  とか ・・・333.333・・・ 順序関係はうまくいきませんが、 ・・・999+1=・・・000=0 と考えると、 ・・・999=-1 といった意味になり、 3をかけることで、 ・・・997=-3 といった意味になったり、 3でわることで、 ・・・333=-1/3 といった意味になったりします。 また、加法と乗法の筆算は、「小数点を中心に左右へ計算」していけば整合性が得られると思われます。 そして、減法・除法も考えられると思います。 つまり、負の実数が構成されたと思います。 結局、左右に無限に続く10進法表記で、実数とその加減乗除が構成されたと思います。 このような、実数の構成はあるのでしょうか? また、不備がありましたら指摘ください。

  • 2桁と3桁の数字の小数点位置を合わせたい

    下方向に小数点2桁の数字を入力しているのですが、2桁と3桁の数字の小数点が ずれてしまいます。 位置を合わせることはできるのでしょうか?

  • float型の精度(有効桁と実数)について

    float型を使った演算の結果で0.0024568という8桁の結果でてきました。 IEEE754の規格により、float型は6~7桁とあるのにナゼ8桁が出てきたのか解りません。 ここで言ってる7桁とは、小数点以下7桁の実数が有効桁と言っているのでしょうか? お詳しい人、無知な自分に教えてください。

  • 化学での有効数字について(途中計算)

     以下についてアドバイスいただけると助かります。  有効数字について  和・差について・・・小数点以下の桁数が少ない方に合わせる  積・商について・・・桁数が少ない方に合わせる  については、分かったのですが、有効数字3桁での指定があるときに  19.1、24.5889、0.12553、3.2952の4つの数にたいして  ○和を筆算で求める場合    小数第1位に合わせるために、    19.1→19.10(小数第2位表示)    24.5889→24.58(小数第3位切り捨て)    0.12553→0.12(小数第3位切り捨て)    3.2952→3.29(小数第3位切り捨て)  として和を求め、小数第1位(小数第2位四捨五入)にする  ○積を筆算で求める場合    有効数字3桁に合わせるために、    19.1→19.10(有効数字4桁表示)    24.5889→24.58(5桁目切り捨て)    0.12553→0.1255(5桁目切り捨て)    3.2952→3.295(5桁目切り捨て)  として積を求め、有効数字を3桁(4桁目は四捨五入)にする  と思っています。  1.このやり方で大学受験では問題ないのでしょうか。    特に気になっているのは、計算をする前の丸め方(すべて切り捨てにしているところ)です。  2.計算ステップがいくつもあり、一度に計算ができない場合、そのステップ毎に得られる数の    丸め方は切り捨て・四捨五入のどちらがよいのでしょうか。  よろしくお願いします。    

  • 小5、少数の割り算筆算について

    小5の子供が算数で少数の割り算、掛け算の筆算をやっているのですが、どうも繰り上げや繰り下がりの足し算、引き算の部分で間違えることが多く困っています。 たぶん、少数の問題でなくても、同じような間違いはよくしています。 この場合、割り算、掛け算の筆算をたくさんやらせた方がいいのでしょうか。 それとも、レベルを下げて足し算、引き算の筆算をやり直させたほうがいいのでしょうか。 何事も繰り返しやることが一番なのでしょうが、 効率のよい勉強の仕方がありましたらどうか教えてください。

  • 単純な計算のスピードがとても遅くて困っています。引き算が特に駄目なんです。

    こんにちは。数学というカテゴリーで質問してもいいのかどうかわかりませんが、他にぴったりのカテゴリーがなかったので ここで質問します。 いつ始まったことか自分でもよくわからない(昔からこうなのかどうか覚えていない)のですが、単純な計算がとても遅くて困っています。 足し算はもちろんとても遅いのですが、問題は引き算です。9-3の答えがすぐに出せません。19-3だともっとダメです。 この数字を見て、足し算(脳内で3+いくつで9になるかな?といちいちたどっていく)をいちいちしないと解けないんです。 本当に答えが出せない、というわけではないのです。5~10秒かければ(単純な計算なら)答えは絶対に出せます。 何桁あっても筆算すれば(スピードは遅いですが)答えは出せます。 そして、とてもおかしな話なのですが、掛け算(1けた×1けた)は人並みに速くできるんです。 足し算と引き算は掛け算と違って、脳内で暗記モードになっていなくていちいち計算しているから遅いんだと思います。 それと、もしかしたらこれも関係があるかもしれないので書いておきますが、 式を目で見ないと、掛け算(1けた×1けた)以外は本当にダメなんです。つまり、口で言われただけだとすごく解きにくいということです。 100ます計算を毎日マル付け時間含めて30分ぐらいやっていた時期が1か月ほどありましたが、前よりちょっと速くなったぐらいで全然だめなんです。 そして、これもまたおかしなことなのですが、歴史年号やら漢字やらの覚えは悪くないんです。 昔そういったことが速くできていたかどうかはよく覚えていませんが、算数、数学の成績は国語や社会に比べて悪かったような気がします。 人並みに引き算と足し算ができるようになる方法を教えてください、よろしくお願いします。

  • 足し算と掛け算の一致

    足し算を1から順に足していきます。 掛け算を1から順に掛けていきます。 和と積が一致するのは、下の例以外に存在するでしょうか? 例 1 = 1 1+2+3 = 1×2×3 1+2+3+4+5+6+7+8+9+10+11+12+13+14+15 = 1×2×3×4×5 掛け算は2の倍数と5の倍数によって、下位の桁に0が続くことになることはわかります。

  • エクセルで引き算、掛け算、割り算をしたい

    いくつか数字を入力して、Σを選択すると足し算になってしまいます。 引き算、掛け算、割り算をしたいのですが、どのように 設定をしたらよいのでしょうか?

  • この歳でかけ算・わり算があやふや

    最初に、質問内容は算数なのにカテゴリを数学にしたことをお許しください。 僕は現在高校1年生の者です。 最近数学の問題を解いていると恥ずかしながらも思うことがあります。 それは、小学生レベルの足し算・引き算・掛け算・割り算の四則演算があやふやになってきているということです。 25×34などは筆算を使ってできるのですが、25×1006とか、筆算のさいに25に0をかけるとなるとやり方が思い出せずにつまづいたりします(でも、1006×25ならできます) あとは小数点・分数を含む掛け算とか、同じく小数点・分数を含む割り算などです。 中学時代や高校入学したて(半年前)の頃はいつもどおり難なくできたのですが、最近はどうやるんだっけ?と忘れた状態になり自信を持って筆算できません。 そこで、その解消方法や四則演算の筆算のやり方などが書かれてある小学生向けの参考書などを教えていただきたいのです。 僕自身Amazonで探してみましたが、『小4の算数』など学年別に分かれていました。僕が小学生のときは1年生で足し引き算、2年生で掛け算、3年生で割り算・・・など四則演算を学年で分割(?)してしまっていたので、もし仮に「小4の算数」を購入したとしても割り算しか演習できないのでは、と思ってしまいます。 しかもゆとり教育のせいで当時○学年で習っていた単元はどの学年へ移ったのかさえもわからないので参考書を選ぶのにも困ってしまいます。 どなたか、教えていただきたいですm(_ _)m

  • 平方根の計算

    平方根の計算の入門編です。 平方根の掛け算はできるのになぜ足し算・引き算はできないのでしょうか。 √2×√3 = √6なのに √2+√3 = √5 になりません。 これまで、数字の計算は足し算引き算かけ算割り算で計算する、と習ってきました。 √がつくとかけ算割り算はできるのに足し算引き算ができません(やってはいけない)また、ルールということはわかりますが、どういうルールなのでしょうか。