数の割り算で「nnn.999・・・」を「nnn」にするには?

解決


S_M_H  2005-08-19 06:43:38  No: 17144

お世話になっています、DELPHI の入門者です。

実数の割り算をすると、数字によっては「nnn.99999・・・」などと
なる時がありますが、これを防ぐには、変数をどのタイプにすれば
良いのでしょうか?
今は Double にしています。
扱う数字は +0.000 〜 +999.999 の間しか使いません。

Delphi の Help で探してるのですが、見つかりません。
たぶん、自分の探し方が悪いんだと思いますが、
「こうだ!!・・・」と教えて頂ければ、うれしいです。

よろしくお願いします。


anone  2005-08-19 07:22:55  No: 17145

ご質問の意味がいまいち理解できません。

> これを防ぐには

1を3で割ると、どのような数なると期待しているんでしょうか?


S_M_H  2005-08-19 08:00:07  No: 17146

大変、変な文になってしまいました。すいません。
割り算ではなく、引き算で出ています。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
public
    Max_n: Double;
    Min_n: Double;
    Def_n: Double;
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
Max_n := StrtoFloat(P1_mae_RT.Text); 
Min_n := StrtoFloat(P2_mae_RT.Text);
Def_n := Max_n - Min_n;
Def_mae_RT.Text := FloattoStr(Def_n);
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
上記で P1_mae_RT.Text には 80.4
       P2_mae_RT.Text には 84.3
がはいっています。
すると、Def_mae_RT.Text には 3.89999 が表示されます。
このようになる数の組み合わせはめったに出ないのですが・・・

上記で、他にも変なところがあるかもしれません。

部分的で分かりにくいと思いますが、よろしくご指導ください。


S_M_H  2005-08-19 08:04:19  No: 17147

すいません、数字の上下が違っていました、

P1_mae_RT.Text には 84.3
P2_mae_RT.Text には 80.4

です。

84.3 - 80.4 = 3.9 のはずが 3.899999・・・

よろしくお願いします。


Mr.XRAY  URL  2005-08-19 08:11:36  No: 17148

Currency 型を調べてみて下さい.
しかし,個人的な意見としては,何故nnn.9999...となってはいけないの
か,最終的な表現がどうあればいいのかを十分考え,検討することをお勧
めします.

ご存知だとは思いますが,コンピュータによる実数の計算には誤差は
つきものです.紙の上での数学の計算とは違います.
極端な話,コンピュータでは,無限小も無限大という数も存在しません.
そして,10進数の有限小数の大部分は,2進数(コンピュータ内部表現)で
は無限小数となります.これが割り切れるはずの数がnnn.9999..となった
りする原因の一つです.

[例]
0.1     0.0001100110011....(2進数)     0.19999999.....(16進数)


Mr.XRAY  URL  2005-08-19 08:16:19  No: 17149

>84.3 - 80.4 = 3.9 のはずが 3.899999・・・

例えば,これでしたら,小数点4桁目で四捨五入すれば,実用的には
十分ですよね.


S_M_H  2005-08-19 08:35:02  No: 17150

早速のご指摘、有り難うございます。

「Currency 型」の所を読んでみます。

「xx.999・・・」この小数部「.999・・・」が実際の数か、誤差表示かを
判別するのが、めんどうだと思いましたので・・・

何かの言語で「10進演算」のような物が有ったように思いましたので、
Delphi でも有るかな〜と思いました。

元の数を 1000 倍し、小数部をなくし、整数演算してもだめでしょうか?
ちょっと試してみます。

アドバイス有り難うございました。


S_M_H  2005-08-19 08:41:08  No: 17151

返信記入中に次が入っていました。

>小数点4桁目で四捨五入すれば,実用的には十分ですよね.

そうですね、これでやってみます。

有り難うございました。


Mr.XRAY  URL  2005-08-19 08:57:32  No: 17152

BCD(2進化10進数)はデータベースの項目値,またDelphi6以上でしたら,
FMTBcdユニットを使用すれば可能です.

[例]
//  usesにFMTBcdが必要

procedure TForm1.Button1Click(Sender: TObject);
var
     A,B,C: TBCD;
begin
     A:=DoubleToBcd(84.3);
     B:=DoubleToBcd(80.4);
     BcdSubtract(A,B,C);
     ShowMessage(BCDToStr(C));
end;

>元の数を 1000 倍し、小数部をなくし、整数演算してもだめでしょうか?

結果が整数である保証があればですね.


S_M_H  2005-08-19 09:17:58  No: 17153

DELPHI は Ver.7です。

「FMTBcdユニット」を使って[例]を参考にしてやってみます。

>結果が整数である保証があればですね

 整数どうしの引き算なので結果は必ず整数?

今日はもう遅いので、結果は明日の夜に報告したいと思います。

BCD(2進化10進数)・・・たぶんOKですね?


S_M_H  2005-08-20 07:44:51  No: 17154

お世話になっています。

「FMTBcdユニット」を使って[例]を参考にしてやってみました。

うまく行きました、手元のデータでは完璧に処理しています。

以下がその抜粋です。
==============================
      If BcdCompare(Max_n , P1_n) = -1 then Max_n := P1_n;
      If BcdCompare(Max_n , P2_n) = -1 then Max_n := P2_n;
      If BcdCompare(Max_n , P3_n) = -1 then Max_n := P3_n;
      If BcdCompare(Max_n , P4_n) = -1 then Max_n := P4_n;
      If BcdCompare(Min_n , P1_n) = 1 then Min_n := P1_n;
      If BcdCompare(Min_n , P2_n) = 1 then Min_n := P2_n;
      If BcdCompare(Min_n , P3_n) = 1 then Min_n := P3_n;
      If BcdCompare(Min_n , P4_n) = 1 then Min_n := P4_n;
      BcdSubtract(Max_n , Min_n , Def_n);
      BcdAdd(P1_n  , P2_n  , BCD_A);
      BcdAdd(P3_n  , P4_n  , BCD_B);
      BcdAdd(BCD_A , BCD_B , BCD_C);
      BcdDivide(BCD_C , 4 , Ave_n);
      Str_Ave := BCDToStr(Ave_n);
      Str_Def := BCDToStr(Def_n);
==============================
最初、普通の IF 文でやっていたらエラーになり、調べたら
専用の BcdCompare が有ったので、それを使ったらすべてうまく
行きました。
IF 文の「=-1」と「=1」は 後々の理解のため明示しときました。

Mr.XRAY さんには色々と教えていただき、有り難うございました。
これで、解決しました。


Mr.XRAY  URL  2005-08-20 09:47:42  No: 17155

うまくいったということで,それでいいとしますが,
10進演算(BCD演算)は,やはり特殊だと思います.もちろん,教育用などで
計算演習などのプログラムでは必要になることあるでしょう.

実数の座標軸を作成するプログラムを作成していますが,この時S_M_Hさん
のような誤差がでると,うまくいきません.しかし,実際の処理は四捨五入
(指定小数点以下の)等で処理しています.

目的によって使い分けが必要でしょうね.
でも,抜粋のコードは,この掲示板をご覧になる他の方にとっても参考に
なるでしょう.


S_M_H  2005-08-20 19:12:10  No: 17156

お世話になっています。

今回の様な5桁以内の数字の処理であれば4捨5入でも良いのでしょうね。
今回のデータでは「−方向の誤差(.9999・・・)」に気付いたのですが、
データによっては「+方向の誤差(.0001・・・)」が出る時も有るのでしょうね。

色々と有り難うございました。
([HomePage]を見ました、たいへん分かりやすく、勉強になります。)


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加