VC++ 初心者です。
VC++6.0 MFC でプログラムを作っています。
質問なのですが、以下のプログラムで a の値が 16121 となってしまいます。
何故でしょうか。
どなたか教えて頂きたく、宜しくお願いします。
int a;
float b;
b=1612.2;
a=(int)(b*(float)10);
1612.2という数字は2進数だと循環小数です。
(b*(float)10)は、16121.9999...となり、
intにキャストするときに切り捨てられて16121。
10進法で例をあげると
3*(1/3) = 3 * 0.333333 = 0.999999
→ 小数点以下を切り捨てて 3 * (1/3) = 0
有限の桁数の計算では避けにくい問題です。
避け方はケースバイケースかな。
桁がそのくらいであれば、とりあえず double にするとか
# double にしても同じ問題は起こりますが
# 有効桁が多くなるので、* 10 したときのずれが少なくなります
> 1612.2という数字は2進数だと循環小数です。
気が付きませんでした(^^;)
float b;
b=1612.2;
printf( %f, b );
で、1612.199951って出たので何でかな?と思っていました。
float使った事がないので(笑)
floatではなくてdoubleを使えば大丈夫だと思うのですが、floatしか使っちゃダメなんでしょ
うか?
a=(int)(b*10.0+0.5); と書いてにげましょう。
値がマイナスだとまずいですねその場合は
a=(int)(b*10.0-0.5); だったかな?
色々な意見有り難うございました。
今回のケースでは、避けられない問題ということが、分かりました。
汎 さんの方法でやることにします。
解決済みですが、、、
> floatではなくてdoubleを使えば大丈夫だと思うのですが、
> floatしか使っちゃダメなんでしょうか?
精度が良くなっても循環小数であることは変わらないので、
正しい数値になる保証はないと思います。
int a = floor(b * 10 + 0.5);
が一番良いのでは?
> 精度が良くなっても循環小数であることは変わらないので、
> 正しい数値になる保証はないと思います。
なるほど、そうですね。
小数点以下1ケタくらいだったら大丈夫でも、仕様が変わってもっと多くの小数点以下を扱うよ
うになったりしたら、バグのもとですね。
↑よくこんな事やったりするんです。