
WinXP,SDKです。
小数点以下第2位までに切り上げをしようと思ったのですが、
以下のような式の場合に0.55が0.56と求められてしまいます。
double num = 0.55;
num = num * 100; <- この時点で55.0
double tmp = ceil(num); <- この時点で56.0 ※
num = tmp / 100; <- この時点で0.56
※の所でなぜ55.0と戻ってこないのでしょうか。
これはなぜか0.55の時だけ現象が出てしまいます。
ほかの数値の場合はほぼ上手く行きます。(ダメな数値は見つけられていません)
上の式をたとえば
num = 55.0;
double tmp = ceil(num);
とした場合、正しく55.0と求められます。
おそらく100をかけているところで何らかの問題が出ていると思うのですが…
100をintやdouble型にしてみても結果は同じでした。
どのように計算すれば上手くいくのでしょうか。
アドバイスをお願い致します。
No.6ベストアンサー
- 回答日時:
2進の小数点以下は近似値でしかないのです。
2の-1乗は0.5、-2乗は0.25・・・
なので0.55をセットした段階で近似値に置き換わっていると思われます。
ただ、デバッグなのど表示では暗黙の丸目が行われていて0.55と表示されているだけでしょう
有効桁で一度丸めを行い切り上げを行うしかないのかも。
私の場合は文字列に変換してから行いましたけど
アドバイスありがとうございます。
はい、デバッグでは小数点以下第14位までしか表示されておらずに、
そこまではすべてゼロだった為になかなか気づきませんでした。
実際は"55.00000000000000700000"と、15位に"7"が入っていました。
今回丸めを行おうと思います。
でも、文字列でやったほうが正しく出来るケースも昔体験したような気がするのですが…
迷っています。
ありがとうございました。
No.5
- 回答日時:
0.55自体が2進表現にした場合に厳密な0.55にならないに起きる現象でしょう
double num = 0.55;
ddum *= 100.0;
double t1 = floor( num );
double t2 = num - t1;
if ( t2 == 0 ) {
printf( "num == 55\t" );
} else {
printf( "num != 55\t" );
}
printf( "%lf", t2 );
printf( "%.20lf", 0.55 );
num = 55.0;
double tmp = ceil(num);
で tmpが55になるのは 55を浮動小数点であらわしても55のまま誤差が無いためです
分かりやすいアドバイスありがとうございます。
何だか基本的な事を分かっていなかったように思います。
55.0を直接入れた時は大丈夫というのもやっと理解出来ました。
こうなるのは当然とやっと分かったので、
処置を考える事が出来そうです。
ありがとうございました。
No.4
- 回答日時:
浮動小数点数で0.55は循環小数になってしまうので、正確に計算することはできません。
多分他にもだめな値はあると思います。
こういった場合には、最初からすべての値を100倍して計算し、最終的な表示の際に100分の1に戻す方法がよく使われます。
アドバイスありがとうございます。
循環小数…このような結果になるのは当たり前なのですね。
分かっているようで分かっていなかったように思います。
0.55*100だけが特殊な訳ではないのですね。
プログラムとしては、小数点以下の有効桁数は6桁で、
0.55*100の小数点以下で0以外のものが発生するのが
15桁目くらいなので、その間くらいで切り捨てをしてから
処理しようかと思います。
ありがとうございました。
No.2
- 回答日時:
やりたいのは切り上げですね
間違えました
見て頂いてありがとうございました。
切り上げとか数値の問題ではないのかもしれません…
あれから色々と調べていて、
普通に
double tmp = 0.55 * 100;
などとしたものを%.20fで表示してみると、
小数点以下第15位くらいに値が入っています。
きっとこれのせいでceilが一つ上に切り上げしてくるんですね。
これは誤差と考えて、
計算式を一度100億倍位にして、切り捨て(floor)してから
ceilにかけたりしてみようかと思います。
ありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# 質問です 下記のコードを分かりやすく解説お願いします 初心者です #include ‹stdio.h 3 2022/05/26 22:03
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
- C言語・C++・C# C言語初心者 ポインタについて、お助けください、、 2 2023/03/15 23:50
- PHP 配列の値の更新方法について 1 2022/08/05 09:49
- PHP カラーミーショップのSmartyでの文字列抜き出し 2 2022/05/06 11:51
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# C pointer? or... 2 2022/03/29 00:47
- Excel(エクセル) VBA フォルダ見える化のコードについて 2 2023/06/19 15:04
- その他(プログラミング・Web制作) このプログラミングをどう組みますか? Googlecolabでやってるんですが、出来る方お願いします 1 2022/07/13 10:52
- C言語・C++・C# C言語でif文が予想と違う動きをする件について7 4 2023/03/20 00:26
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
プログラムでの数字につく”f”の...
-
C言語 関数プロトタイプ宣言の...
-
物体が往復する動きを作りたい
-
doubleの変数にintとintの割り...
-
float型とdouble型の変数の違い...
-
文字列をfloatで読み込む(atoi,...
-
C言語を実行すると-infが出てき...
-
C言語 初心者です
-
C言語の型による処理速度の違い
-
DWORDの警告
-
C言語初心者 構造体 課題について
-
Cプログラミングの問題です。ニ...
-
至急です! マクロ定義で #defi...
-
C言語で-23乗を取り扱うには
-
C 開放してるのにエラー(doubl...
-
sin(x)の近似について
-
c言語のコンパイルエラー canno...
-
C言語(プログラミング)関連の質...
-
関数におけるif文とreturn文に...
-
2次方程式の解を求めるプログ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
プログラムでの数字につく”f”の...
-
float型とdouble型の変数の違い...
-
C言語を実行すると-infが出てき...
-
C 開放してるのにエラー(doubl...
-
c言語で、繰り返し文の中で、0....
-
doubleの変数にintとintの割り...
-
至急です! マクロ定義で #defi...
-
C言語の型による処理速度の違い
-
C言語 関数プロトタイプ宣言の...
-
2次方程式の解を求めるプログ...
-
関数におけるif文とreturn文に...
-
doubleは常に%lfとするべきなのか
-
int とdoubleの比較
-
C言語のプログラムで#include<m...
-
C言語で-23乗を取り扱うには
-
データ数の多い構造体配列
-
指数の表示
-
C言語のpow関数の不具合
-
c言語のプログラミングについて...
-
c言語のコンパイルエラー canno...
おすすめ情報