The documentation says:
TFMTBCDField encapsulates the fundamental behavior common to binary-coded decimal (BCD) fields. BCD values provide greater precision and accuracy than floating-point numbers. BCD fields are often used for storing and manipulating monetary values.
Unfortunately, I'm finding that using such a field in combination with an Extended
value, I'm losing precision (in this example two digits): if I use
BcdField.AsExtended := Value;
the value gets actually truncated to four digits. What can I do about this?
Complete example:
procedure TForm1.Button1Click(Sender: TObject);
var
LValue: Double;
LDataset: TClientDataSet;
LFieldDef: TFieldDef;
begin
LValue := 1 / 3;
LDataset := TClientDataSet.Create(self);
try
LFieldDef := LDataset.FieldDefs.AddFieldDef;
LFieldDef.DataType := ftFMTBcd;
LFieldDef.Size := 6;
LFieldDef.Precision := 10;
LFieldDef.Name := 'A';
LDataset.CreateDataset;
LDataset.Append;
LDataset.FieldByName('A').AsExtended := LValue;
LDataset.Post;
ShowMessage(FloatToStr(LDataset.FieldByName('A').AsExtended));
ShowMessage(FloatToStr(LValue));
finally
FreeAndNil(LDataset);
end;
end;
Output (in message boxes):
0,3333
0,333333333333333
Strictly speaking it would be more accurate to use TField.AsBCD
which returns a TBcd
record. TFmtBcdField
overrides the default implementation and returns an accurate TBcd
record.
TBcd
is a record structure with support for simple arithmetic operators and implicit conversion from Integer
and Double
. So it should be suitable for most purposes.
The drawbacks are:
Double
or Integer
parameters may need TBcd
overload implementations.Some related considerations:
Double
is not appropriate if you require accurate precision due to the nature floating point representation. See Is floating point math broken? for more info.Extended
has the same problems as Double
even though the extra 2 bytes provide greater range and higher precision - it's still a floating point data type. Furthermore, Extended
has its own problems. Take note of the warnings here.Double
using BcdToDouble
. See BCD Support Routines.Currency
data type. It's represented as a 64-bit integer with assumed division by 10000 which is how it supports 4 decimal digits.