ページ 11

初歩的な質問

Posted: 2011年10月12日(水) 22:22
by detteiu
最近C言語の勉強を始めたものです。

定価の○割引を求めるプログラムを作ってみたのですが、
以下のプログラムで8割引きの値段が20円にならないのはなぜでしょうか?
また、初カキコなので書き込み方やプログラムの書き方等、他にもご指摘あればよろしくお願いします。

プログラム↓

コード:

 
#include <stdio.h>

int main(void)
{
	int teika;

	printf("定価を入力してください。\n");
	
	scanf("%d",&teika);

	printf("定価の1割引きの値段は、%d 円。\n",(int)(teika * (1 - 0.1)));
	printf("定価の3割引きの値段は、%d 円。\n",(int)(teika * (1 - 0.3)));
	printf("定価の5割引きの値段は、%d 円。\n",(int)(teika * (1 - 0.5)));
	printf("定価の8割引きの値段は、%d 円。\n",(int)(teika * (1 - 0.8)));

	return 0;

}
 
実行結果↓

定価を入力してください。
100
定価の1割引きの値段は、90 円。
定価の3割引きの値段は、70 円。
定価の5割引きの値段は、50 円。
定価の8割引きの値段は、19 円。

Re: 初歩的な質問

Posted: 2011年10月12日(水) 22:39
by box
detteiu さんが書きました: 以下のプログラムで8割引きの値段が20円にならないのはなぜでしょうか?
コンピューターでは二進法を使っているがゆえの宿命です。
2のべき乗の和で表せない数値をコンピューターで扱う際、どうしても誤差が生じます。

質問者さんのところでは、
1-0.8
は、「ぴったり」0.2になるのではなく、おそらく
0.199999999......
という、「0.2にきわめて近いが、ほんのわずかだけ小さい」数値なのでありましょう。

というわけで、それに100を掛けて整数部を取り出すと、19になるのです。

Re: 初歩的な質問

Posted: 2011年10月12日(水) 22:48
by box
ちなみに、私のところで下記のプログラムを実行すると、
0.20000000000000001000
という結果を得ました。
私が使っているコンパイラーでは、「たまたま」0.2よりほんの少しだけ大きい値となる、ということでありましょう。

コード:

#include <stdio.h>

int main(void)
{
    printf("%.20f\n", 0.2);
    return 0;
}

Re: 初歩的な質問

Posted: 2011年10月12日(水) 22:56
by hss12
90円70円50円もたまたま正解が表示されているだけです。
例えばこう書けば問題はありません。

コード:

#include <stdio.h>

int main(void)
{
	int teika;

	printf("定価を入力してください。\n");
	scanf("%d",&teika);

	printf("定価の1割引きの値段は、%d 円。\n",(int)(teika * (10 - 1))/10);
	printf("定価の3割引きの値段は、%d 円。\n",(int)(teika * (10 - 3))/10);
	printf("定価の5割引きの値段は、%d 円。\n",(int)(teika * (10 - 5))/10);
	printf("定価の8割引きの値段は、%d 円。\n",(int)(teika * (10 - 8))/10);

	return 0;
}
消費税を求めるプログラムの場合1.05をかけるのではなく105をかけて100で割ったほうがよいです。

回答ありがとうございました。

Posted: 2011年10月12日(水) 23:32
by detteiu
実数を使って表した方がわかりやすいかと思っていましたが、計算で誤差がでてしまうんですね;
これからはなるべく整数を使っていこうと思います。

迅速な回答ありがとうございました。

Re: 初歩的な質問

Posted: 2011年10月12日(水) 23:34
by detteiu
解決しました。

Re: 回答ありがとうございました。

Posted: 2011年10月12日(水) 23:47
by box
detteiu さんが書きました: これからはなるべく整数を使っていこうと思います。
そういう結論で本当にいいかどうかは再考の余地があると思います。