整数に変換すると値がずれるのは何故 – プログラミング – Home

整数に変換すると値がずれるのは何故
 
通知
すべてクリア

[解決済] 整数に変換すると値がずれるのは何故


みのすけ
 みのすけ
(@みのすけ)
ゲスト
結合: 22年前
投稿: 64
Topic starter  

VC++ 初心者です。

VC++6.0 MFC でプログラムを作っています。
質問なのですが、以下のプログラムで a の値が 16121 となってしまいます。
何故でしょうか。
どなたか教えて頂きたく、宜しくお願いします。

int a;
float b;

b=1612.2;
a=(int)(b*(float)10);


引用未解決
トピックタグ
たいちう
 たいちう
(@たいちう)
ゲスト
結合: 23年前
投稿: 662
 

1612.2という数字は2進数だと循環小数です。
(b*(float)10)は、16121.9999...となり、
intにキャストするときに切り捨てられて16121。

10進法で例をあげると
3*(1/3) = 3 * 0.333333 = 0.999999 
→ 小数点以下を切り捨てて 3 * (1/3) = 0

有限の桁数の計算では避けにくい問題です。
避け方はケースバイケースかな。


返信引用
たみあ
 たみあ
(@たみあ)
ゲスト
結合: 22年前
投稿: 57
 

桁がそのくらいであれば、とりあえず double にするとか

# double にしても同じ問題は起こりますが
# 有効桁が多くなるので、* 10 したときのずれが少なくなります


返信引用
ひろぴー
 ひろぴー
(@ひろぴー)
ゲスト
結合: 22年前
投稿: 182
 

> 1612.2という数字は2進数だと循環小数です。
気が付きませんでした(^^;)
float b;
b=1612.2;
printf( %f, b );

で、1612.199951って出たので何でかな?と思っていました。
float使った事がないので(笑)

floatではなくてdoubleを使えば大丈夫だと思うのですが、floatしか使っちゃダメなんでしょ
うか?


返信引用
汎
 汎
(@汎)
ゲスト
結合: 22年前
投稿: 43
 

a=(int)(b*10.0+0.5); と書いてにげましょう。


返信引用
汎
 汎
(@汎)
ゲスト
結合: 22年前
投稿: 43
 

値がマイナスだとまずいですねその場合は
a=(int)(b*10.0-0.5); だったかな?


返信引用
みのすけ
 みのすけ
(@みのすけ)
ゲスト
結合: 22年前
投稿: 64
Topic starter  

色々な意見有り難うございました。

今回のケースでは、避けられない問題ということが、分かりました。

汎 さんの方法でやることにします。


返信引用
たいちう
 たいちう
(@たいちう)
ゲスト
結合: 23年前
投稿: 662
 

解決済みですが、、、

> floatではなくてdoubleを使えば大丈夫だと思うのですが、
> floatしか使っちゃダメなんでしょうか?

精度が良くなっても循環小数であることは変わらないので、
正しい数値になる保証はないと思います。

int a = floor(b * 10 + 0.5);
が一番良いのでは?


返信引用
ひろぴー
 ひろぴー
(@ひろぴー)
ゲスト
結合: 22年前
投稿: 182
 

> 精度が良くなっても循環小数であることは変わらないので、
> 正しい数値になる保証はないと思います。
なるほど、そうですね。
小数点以下1ケタくらいだったら大丈夫でも、仕様が変わってもっと多くの小数点以下を扱うよ
うになったりしたら、バグのもとですね。
↑よくこんな事やったりするんです。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました