以下のプログラムは電卓のプログラムです。
http://codepad.org/n47BkpXa
このプログラムの変数の宣言はあえてint型で行っています。
コレを変えずに上手く計算結果が出せるようにしたいのですが、どこを修正すれ良いですか?
ご指導お願いします。
・問題点
例:10/4*4などの最初に割り算が入ると計算結果がおかしくなってしまいます。
10/4*4=8 int型なので小数点が切り捨てられて結果が8になってしまいます。
コレをint型を使用して10になるようにしたいのですがご指導お願いします。
多分イメージではif文で(op=/)&&(op+1=*)が出たら掛け算を始めにするとかだと思います。
No.8ベストアンサー
- 回答日時:
ANo.2, 7です。
ANo.7ではcalc関数を修正しない方が良いと言いましたが、
ちゃんと計算できるように追加コード部分を修正してみました。
修正箇所は
if((*op == '/') && (*(op + 1) == '*')){/*op='/'、op+1='*'が入った時*/
*x = (*x) * (*(x + 2));
printf("answer1 = %d\n",*x);
*(x + 2) = *x / *(x + 1) ;
printf("answer2 = %d\n",*(x + 2));
return *x;
}
の部分です。これを
if((*op == '/') && (*(op + 1) == '*')){/*op='/'、op+1='*'が入った時*/
*x = (*x) * (*(x + 2));
printf("answer1 = %d\n",*x);
*(x + 2) = *x / *(x + 1) ;
printf("answer2 = %d\n",*(x + 2));
// return文は不要
// 以下5行が追加コード
*x = 0;
*(x + 1) = 0;
x = x + 2;
op = op + 2;
continue;
}
と直すと上手くいきます
(インデントに全角スペースを使っているので注意して下さい)。
*x = 0や*(x + 1) = 0が必要な理由は、
calc関数内のswitch文で*x = 0が実行されている理由と同じなのですが、
何故このコードが必要なのかは分かりますか?
この修正をすれば10/4*4のように、
「わり算1回、かけ算1回を行う式」には上手く対応できます。
しかし10/4/5*5*4や10/4/5*4*5のように、
「わり算が2回以上連続して続いた後にかけ算がある式」には対応できません。
これは追加コードでは、隣り合うわり算、かけ算のみを処理しているのが原因です。
例えば10/4/5*5*4では/5と*5は追加コード部分でうまく処理されるのですが、
位置が離れている/4と*4は処理されません。
これで妥協するかどうかは質問者さんに任せます。
妥協したくないなら、このコードを更に修正するか、
あるいは別の方法を取る事になります。
No.7
- 回答日時:
追加コードの部分にreturnがあります。
これではwhileループで全ての数を処理する前に
calc関数を抜けてしまいます。
計算結果がおかしくなるのはそのためだと思います。
こういう面倒なことがあるので、並び替えの処理は
calc関数の中でやらない方がいいと思います。
並び替えだけを行う関数を作り、main関数の中で
(1) 並び替え関数
(2) calc関数(mode =1)
(3) calc関数(mode =0)
の順番で関数を呼び出せば良いと思いますが…。
No.6
- 回答日時:
掛け算を先にやったらオーバーフローの可能性があるんだけど, そこには目をつむるってのが理解できん.
たとえば, int が 32ビットの環境で
1000000 / 100001 * 100001
を計算すると掛け算を先にやっても割算を先にやっても「期待した結果」にはならないはずなんだけど, そんなんでいいのか?
この回答への補足
いいです。
高精度な計算結果は求めていません。
自分が途中まで出来たのを入れます。
条件分岐を入れてみましたが、最終的な結果はおかしくなってしまいます。
下記にソースを入れます。修正箇所を教えて頂けますか?
#include <stdio.h>
#include <stdlib.h>
/*
int check_num(int *x, char *op)
{
inti;
while(*op != '=') {
for(i=0; i<10; i++) {
x[i] == *(x + i);
if(*(op + i) == '='){
calc(x, op , 1);
}
}
}
}
*/
int calc(int *x, char *op, int mode) /* x=項、op=演算子、mode=0か1で処理を分岐*/
{
while (*op != '=') {/*opに'='が代入されるまで回す*/
if (mode==0) {/*mode=0の処理(mode=1で得た計算結果を最後に加算する)*/
*(x + 1) = *(x+1) + (*x);
x++;/*配列に入れられた値を更新*/
op++;/*'='が出されるまでopを更新*/
}
if (mode==1) {/*mode=1の処理(乗算、除算、減算を行って、計算結果を配列に入れる)*/
if((*op == '/') && (*(op + 1) == '*')) {/*op='/'、op+1='*'が入った時*/
*x = (*x) * (*(x + 2));
printf("answer1 = %d\n",*x);
*(x + 2) = *x / *(x + 1) ;
printf("answer2 = %d\n",*(x + 2));
return *x;
}
switch (*op) {
/*乗算*/
case '*':
*(x + 1) = (*x) * (*(x + 1));/*例:x+1=4(x)×2(x+1)*/
*x = 0;
break;
/*除算*/
case '/':
*(x + 1) = *x / *(x + 1);/*例:x+1=4(x)÷2(x+1)*/
*x = 0;
break;
/*減算*/
case '-':/*例:x+1=2×(-1)*/
*(x + 1) = *(x+1) * (-1);/*最後に加算を行うので値をマイナスにして配列に入れる*/
break;
}
x++;
op++;
}
}
return *x;
}
intmain(void)
{
int x[10];/* 項 */
char op[10];/* 演算子 */
int i;
while (1) {
printf("式を入力してください\n");
printf("例:1*2+5=enter \n");
printf("式:");
for (i = 0; i<10; i++) {/*10項まで計算可*/
scanf("%d %c", x + i, op + i);
if (*(op + i) == '=')/*op='='が代入されるまで回し続ける*/
break;
}
calc(x, op, 1);
printf("答え:%d\n", calc(x, op, 0));/*mode=0の処理へ移行(最後に加算をして結果を出力)*/
}
/* return 0;*/
}
No.5
- 回答日時:
>割り算と掛け算の順序を逆転させるという、
>数式解析のむずかしい技を使ってまで
>int型にこだわる理由が全くわかりません。
>講師の方がこういう課題を出してきました。結構、天邪鬼なかたなので。
まともなプログラマなら少数または分数処理するものを、整数にこだわる講師はまともでありません。講師本人の知識を披露したいだけのバカです。
この手のくだらない事に頭を使わずに、学校に抗議して講師を変えてもらったほうが良いです。
No.4
- 回答日時:
割り算と掛け算の順序を逆転させるという、
数式解析のむずかしい技を使ってまで
int型にこだわる理由が全くわかりません。
もしよかったら、その理由を教えていただけますか?
この回答への補足
自分も正直そう思います。
しかし、講師の方がこういう課題を出してきました。結構、天邪鬼なかたなので。
ヒントでは左辺に'÷'右辺に'×'がきたら掛け算を行うということらしいですが、貼り付けてあるソースは
計算された値を一度配列に格納してから、最後に加算しているので難しいと思います。
すみませんが、お力添えをお願いします。
No.3
- 回答日時:
固定小数という考え方があります。
32bitのint型なら、左側16bitが整数部、右側16bitが小数部として扱う。
この方法ですと整数型で計算することが可能ですが、ただし有効桁数が
浮動小数のfloat、doubleに比べ小さいことに留意しましょう。。
固定小数点演算
http://www2.muroran-it.ac.jp/circle/mpc/front/ol …
参考URL:http://www2.muroran-it.ac.jp/circle/mpc/front/ol …
No.2
- 回答日時:
計算をする前に因数の順番を入れ換えれば良いと思います。
かけ算わり算で繋がっているところを見つけ、
その部分を、かけ算がわり算よりも左側に来るように並べかえるんです。
この前処理さえしてしまえば、
計算処理をするコードを書き換える必要はなくなります。
ただこの方法でも、1 / 2 + 1 / 2のような式には対応できません。
こういった式も処理したいなら、int型整数を2つ使って分数を表現し、
分数を使って計算処理をするという方法が考えられます。
No.1
- 回答日時:
無理です。
int型では常に少数部のカットが行われるのでどうしようもありません。言語仕様ですから、どうしても「10/4*4」の計算で常に「10」と正しい答えを出したいのならフロート型かダブル型を使用して最終的に少数部切ってください。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語 3 2022/10/04 15:07
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# このプログラミングの問題を教えてほしいです。 キーボードからデータ数nとn個のデータを入力し、平均値 3 2022/12/19 22:51
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- C言語・C++・C# C言語階乗の総和を求める 2 2023/03/04 23:31
- C言語・C++・C# このプログラミングの問題を教えて欲しいです。 キーボードから整数kを入力し、kが配列aの中に何個存在 2 2022/12/19 22:50
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# C言語 3 2022/11/09 13:27
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
- C言語・C++・C# 3×3のラテン方陣をつくるプログラムを作成したのですが、(↓) #include <stdio.h> 5 2023/07/10 01:53
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
65536は2の何乗なのでしょうか?
-
Javaを使った行列計算
-
VBAで関数をつくる
-
プログラムの質問
-
再帰呼び出しを用いるnPk,nCk ...
-
VBでReplace
-
Java 電卓の連続計算
-
階乗のマクロ
-
変化させるセルが変化しない
-
バッチファイルでウインドウを...
-
VB6で 1-0.1*10 の計算結果が...
-
情報処理 ポインタ渡しによる...
-
傾いた四角形内の範囲の条件式
-
[ASP]日付と時間の比較
-
matlabで計算終了
-
数値計算の高速化 (cos, sin, exp)
-
C言語のプログラミングの問題で...
-
CCurの引値を文字列にする時と...
-
継承元と継承先での変数
-
EXCELなどで「返す」という表現
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
65536は2の何乗なのでしょうか?
-
VBAの再計算が反映されない件に...
-
排他的論理和 BCC(水平パリテ...
-
EXCELなどで「返す」という表現
-
C言語の課題で、1年の秒数を計...
-
バッチファイルでウインドウを...
-
骨折リスク評価のFRAXについて...
-
変化させるセルが変化しない
-
CとFORTRANの計算速度はどちら...
-
なぜオーバーフローになるので...
-
数値計算の高速化 (cos, sin, exp)
-
モジュラス103の計算とは何でし...
-
C# 計算処理中に実行中ウィン...
-
モジュロ
-
60進数の四則計算
-
C言語についてです。 再帰を使...
-
引き放し法による除算アルゴリ...
-
Perlで時間の計算
-
傾いた四角形内の範囲の条件式
-
CRC8を教えてください
おすすめ情報