BCD

 Delphi 6のFMTBcdルーチン。いたるところで精度の自動調整が行なわれるのだが、その際、絶対値が1未満の数値に対する処理が×らしく、小数点が行方不明に。例えば、

Memo1.Lines.Add(BcdToStr(StrToBcd('0.1')));

で’1’と表示されるし、

BcdDivide('1','10',B); // B := 1 / 10
Memo1.Lines.Add(FormatBcd('#.#',B));

も’1’、

if BcdToDouble(DoubleToBcd(0.1)) = BcdToDouble(DoubleToBcd(1.0)) then
begin
  Memo1.Lines.Add('一致');
end;

が’一致’してしまう。1.111を10で割ると1111となり、

B := StrToBcd('1111');
for I := 1 to 50 do
begin
  BcdDivide(B,10,B); // B := B / 10
  Memo1.Lines.Add(BcdToStr(B));
end;

という処理では1.111から1111までの間を行ったり来たり…。
まあ、整数部が常に1桁以上となるよう調整、つまりは、

CurrToBCD(0.1,B);
Memo1.Lines.Add(BcdToStr(B));

NormalizeBcd(StrToBcd('0.1'),B,64,32);
Memo1.Lines.Add(BcdToStr(B));

とでもすれば良いのだが、そうするくらいなら通常の実数型を使うほうがマシというもの。また、上記の処理を

B := StrToBcd('0.1');
NormalizeBcd(B,B,64,32);
Memo1.Lines.Add(BcdToStr(B));

とすると’0’になる。これはNormalizeBcd関数の第1パラメータがconst指定であるが故。あらかじめ、

function NormalizeBcd(InBcd: TBcd; var OutBcd: TBcd; const Prec, Scale: Word): Boolean;
begin
  Result := FMTBcd.NormalizeBcd(InBcd,OutBcd,Prec,Scale);
end;

とでもしておかないと危険。
にしても、精度が命のBCDにおいて、「自動調整」ってのは…?

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください