ページ 11

質問です

Posted: 2012年7月19日(木) 17:31
by 大田のボム兵
初めまして。C言語超初心者です。
質問なんですが、定価と個数を入力すると価格、税込価格、お釣り、2割り引きの値段を表示して、税込価格が105000円を超えると
「金額が大き過ぎます。
 再入力して下さい。」
と表示して再入力させるプログラムを練習で作ってみたのですが実行すると意味不明な数値が出てきてしまいます。

以下コード

コード:

#include <stdio.h> 

int main(void){ 
int x,y,z,s,a,m; /* xは定価を定義、yは個数を定義、zはxとyの積を定義、sは消費税計算を定義、aは2割引の金額を定義、mは金額1000を定義 */ 
do { 

printf ("定価を入力して下さい:"); scanf ("%d",&x); 
printf ("個数を入力して下さい:"); scanf ("%d",&y); 

z = x*y; 
s = (z*105)/100; 
a = s*0.8; 
m = 1000; 

if (s > 105000){ 
printf ("金額が大き過ぎるため再入力をお願いします。\n※合計値を105000以内にして下さい。\n"); /* 税込価格が105001円以上の場合表示 */ 
} 

} while (s > 105000); /* 税込価格が105001円以上の場合、6行目do~20行目while(s > 105000);まで繰り返す */ 
/* 税込価格が105000円以内の場合、税込価格に応じて下記のプログラムを実行する。 */ 

if (s <= 1000) { 
printf ("価格は%d円で、税込み価格は%dです。\nまた、千円を出した場合のお釣りは%d円で、2割引の値段は%d円です。",z,s,m-s,a); 
} else { 
if (s > 1000 && s <10000) { 
printf ("価格は%d円で、税込み価格は%dです。\nまた、一万円を出した場合のお釣りは%d円で、2割引の値段は%d円です。",z,s,(m*10)-s,a); 
} else { 
if (s >= 10000 && s <= 105000) { 
printf ("価格は%d円で、税込み価格は%dです。\nまた、10万円を出した場合のお釣りは%d円で、2割引の値段は%d円です。",z,s,(m*100)-s,a); 
} 
} 
} 
return 0; 
} 
(/code]

価格と個数をどちらも12345にすると意味不明な数字が出てきます。 
他の計算や123456×123456や12345×123456だと正常に動作するのに何故こうなるのでしょうか? 
あと税込価格が100兆円を超えてもなります。(intを使ってるからですか?)
もしよろしければ原因を教えてください。 
貴重なスペースを使ってしまって申し訳ありません。

Re: 質問です

Posted: 2012年7月19日(木) 17:48
by non
恐らく、intの範囲を超えているからだと思いますが、それについては環境をお答えいただかないと正確には
わかりません。
ただ、それなら123456×123456や12345×123456も、正常に動作するはずがありません。

Re: 質問です

Posted: 2012年7月19日(木) 18:12
by 大田のボム兵
ご返答頂きありがとうございます。
ほんとに初心者なので初歩的な質問で申し訳ないのですが、環境とは使用してるコンパイラ?でいいのでしょうか?
あと訂正なのですが123456×123456でも変になりました。
12345×123456は平気でした。

Re: 質問です

Posted: 2012年7月19日(木) 20:22
by nil
本題とは離れますが、少し気になった点があったので、
a = s*0.8;
int 型の計算にdouble型を用いるのはよくありません。
double型には誤差があり、予期せぬ値になる可能性があります。
s = (z*105)/100;
これと同じで整数を用いて演算を行うほうが良いでしょう。

Re: 質問です

Posted: 2012年7月19日(木) 21:14
by 大田のボム兵
ご指導頂きありがとうございます。

a =(s*8)/10;

ってことですよね?

Re: 質問です

Posted: 2012年7月20日(金) 09:03
by non
>環境とは使用してるコンパイラ?でいいのでしょうか?
お使いのコンパイラですね。
次のプログラムを試してください。

コード:

#include <stdio.h>
#include <limits.h>   

int main(void)
{
    printf("int の最大値: %d\n", INT_MAX);
	return 0;
}
これを実行すると、intで扱える最大の数が返ってきます。
私の環境(VisualC++2008ExpressEdition)ですと、
2147483647 です。
12345*12345は、152399025なので、intの範囲です。
しかし、
s = (z*105)/100; を行うと、先に105倍するので、intの範囲を超えます。
だから、おかしな答えになってしまいます。

>12345×123456は平気でした。
これもおかしいはずです。

コード:

if (s > 105000){ 
printf ("金額が大き過ぎるため再入力をお願いします。\n※合計値を105000以内にして下さい。\n"); /* 税込価格が105001円以上の場合表示 */ 
} 
これで、再入力になっていますか?

Re: 質問です

Posted: 2012年7月20日(金) 10:12
by asd
横から失礼します。
non さんが書きました:

コード:

if (s > 105000){ 
printf ("金額が大き過ぎるため再入力をお願いします。\n※合計値を105000以内にして下さい。\n"); /* 税込価格が105001円以上の場合表示 */ 
} 
これで、再入力になっていますか?
CODEタグの閉じタグが間違っていて見づらいのですが、
当該の入力処理箇所はdo-while文で囲まれているので、sのint上限値を超える問題はあるものの
105,000円を超えた場合はwhileの条件式により再度入力処理が行われると思います。

コード:

do {

    printf ("定価を入力して下さい:"); scanf ("%d",&x);
    printf ("個数を入力して下さい:"); scanf ("%d",&y);

    z = x*y;
    s = (z*105)/100;
    a = s*0.8;
    m = 1000;

    if (s > 105000){
        printf ("金額が大き過ぎるため再入力をお願いします。\n※合計値を105000以内にして下さい。\n"); /* 税込価格が105001円以上の場合表示 */
    }
} while (s > 105000); /* 税込価格が105001円以上の場合、6行目do~20行目while(s > 105000);まで繰り返す */ 
・編集2012/07/20 10:13
誤字訂正

Re: 質問です

Posted: 2012年7月20日(金) 10:25
by non
non さんが書きました: >12345×123456は平気でした。
これもおかしいはずです。

コード:

if (s > 105000){ 
printf ("金額が大き過ぎるため再入力をお願いします。\n※合計値を105000以内にして下さい。\n"); /* 税込価格が105001円以上の場合表示 */ 
} 
これで、再入力になっていますか?
私がいいたいのは、12345×123456の場合は再入力になっていますかと尋ねたのです。
asd さんが書きました:
CODEタグの閉じタグが間違っていて見づらいのですが、
別に間違ってはいないと思うけど。
閉じタグの前に改行を入れればいいのかな。

「編集追加」
ああ、これってスレ主さんへの・・・

Re: 質問です

Posted: 2012年7月20日(金) 10:39
by asd
non さんが書きました:
non さんが書きました: >12345×123456は平気でした。
これもおかしいはずです。

コード:

if (s > 105000){ 
printf ("金額が大き過ぎるため再入力をお願いします。\n※合計値を105000以内にして下さい。\n"); /* 税込価格が105001円以上の場合表示 */ 
} 
これで、再入力になっていますか?
私がいいたいのは、12345×123456の場合は再入力になっていますかと尋ねたのです。
なるほど、そういう意図でしたかすみません。
if文の箇所だけが抜き出されていたので、sがintの範囲内でかつ105,000を超えていても再入力(ループ)しないのでは?と
問うているように見えました。
non さんが書きました:
asd さんが書きました:
CODEタグの閉じタグが間違っていて見づらいのですが、
別に間違ってはいないと思うけど。
閉じタグの前に改行を入れればいいのかな。

「編集追加」
ああ、これってスレ主さんへの・・・
言葉足らずですみません。
編集追加でのご推察の通り、スレ主さんの質問文中での話でしたm(_ _)m
お騒がせしました。