• ベストアンサー

VCでキャストに失敗する

double ddd; double ddd2; long lll; long lll2; ddd = -3.038; ddd = ddd*10000.0; ddd2 = -30380.0; lll=(long)ddd; lll2=(long)ddd2; 上記のような処理をした場合に lllは-30379になり lll2は正しい-30380になります。 なぜlllでは-1されてしまうのでしょうか? どなたかお教えください、よろしくお願いします。 コンパイル環境はVC6.0 OSはWomdowsNT SP6です。

質問者が選んだベストアンサー

  • ベストアンサー
  • BILLY-J
  • ベストアンサー率57% (60/105)
回答No.1

こんにちは。 double はあくまでも近似値であるが故に顕著な誤差が現れる場合 が有ります。私も軽く試してみましたが、今回の -3.038 という値は 絶対値に対して負の誤差を含んでしまうため、整数化した時に違い が現れます。 悲しい事に初期値代入の時点から誤差が含まれていました。 ddd = -3.038; printf("ddd = %.20f \n", ddd); → ddd = -3.03799999999999981200 ddd = ddd * 10000.0; printf("ddd = %.20f \n", ddd); → ddd = -30379.99999999999636000000 このまま実数計算を続けるなら無視できるオーダーの誤差なのかも 知れませんが、整数化する場合は見た目上許せない結果ですよね(笑) 対処療法ですが、誤差分を四捨五入してから切り捨てるのは如何 でしょうか。 lll = (long)ddd;   ↓ lll = (long)(ddd * 10.0); if (0 < lll) {   lll = lll + 5; } else if (0 > lll) {   lll = lll - 5; } lll = lll / 10; (絶対値等を使えばもう少しスマートなコードになるかも…) 1桁余分に整数化し、その桁で四捨五入してから切り捨てます。 余分に取った桁が含む誤差は-1~+1でしょうから、四捨五入も 大袈裟ですが、逆に問題も無いように見えます。 しかし、あまり深くは検証していませんので悪しからず… ※誤差はコンパイラの問題ではありません、念のため。  私はVC以外のコンパイラで試しました。

kazubon-X
質問者

お礼

そうですか、コンパイラの問題ではなかったんですね。 ありがとうございました。 参考にさせて頂きます。

関連するQ&A