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において、「自動調整」ってのは…?