How can I avoid losing precision with ftFmtBcd?

ventiseis

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
Disillusioned

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:

  • Mathematical operations may be marginally slower due to lack of built in machine instruction. But it's probably a reasonable trade-off for cases where precise representation is required. Benchmark and evaluate as needed.
  • Some functions that take Double or Integer parameters may need TBcd overload implementations.

Some related considerations:

  • The use of 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.
  • The use of 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.
  • If you don't need precise representation, then you can convert to Double using BcdToDouble. See BCD Support Routines.
  • Another option to consider in cases where you don't need more than 4 decimals, but do need precise representation: Use the Currency data type. It's represented as a 64-bit integer with assumed division by 10000 which is how it supports 4 decimal digits.

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

How can I avoid "environment hell" in postman?

分類Dev

How can I avoid a circular reference situation

分類Dev

Django conditional queries: How can I avoid this?

分類Dev

How can I avoid duplicate templates in Meteor?

分類Dev

How i can avoid the distinct() of watchdog?

分類Dev

How can I avoid problems with CPU power?

分類Dev

How can can I simplify a basic mesh without losing any shape at all?

分類Dev

avoiding losing precision with nawk option

分類Dev

How can I convert an ext4 partition to btrfs (or other file systems) without losing data?

分類Dev

How can I change the order of accessibility elements in a view controller without losing access to the navigation bar?

分類Dev

How can I un-export a variable, without losing its value?

分類Dev

How can I hide/show html elements without losing initial CSS Styling?

分類Dev

How can I convert a drive from ext4 to NTFS without losing the data?

分類Dev

How can I avoid nested Navigation Bars in SwiftUI?

分類Dev

How can I avoid running some tests in parallel?

分類Dev

How can I avoid Phusion Passenger running as root?

分類Dev

How can I avoid using 'at' in radial-gradient?

分類Dev

How can i avoid Jquery translate `?` to `%3F`

分類Dev

How can I avoid overwriting dynamodb from two lambdas?

分類Dev

EXC_BAD_ACCESS - How can I avoid it?

分類Dev

How can i avoid or pass over a directory that is access denied?

分類Dev

How can I avoid repeating the css and not using !important?

分類Dev

How can I avoid a black background when fading in an overlay with ffmpeg?

分類Dev

Can I avoid mutating in this scenario?

分類Dev

Can i have ubuntu on SSD and WIndows on HDD without losing fils?

分類Dev

Can I downgrade Vscode without losing my extensions?

分類Dev

How can I avoid my program to keep running when I close my main frame?

分類Dev

How can I avoid Firefox's "you have chosen to open" dialog when I try to download a file?

分類Dev

Can I avoid nested namespaces in forward declaration?

Related 関連記事

  1. 1

    How can I avoid "environment hell" in postman?

  2. 2

    How can I avoid a circular reference situation

  3. 3

    Django conditional queries: How can I avoid this?

  4. 4

    How can I avoid duplicate templates in Meteor?

  5. 5

    How i can avoid the distinct() of watchdog?

  6. 6

    How can I avoid problems with CPU power?

  7. 7

    How can can I simplify a basic mesh without losing any shape at all?

  8. 8

    avoiding losing precision with nawk option

  9. 9

    How can I convert an ext4 partition to btrfs (or other file systems) without losing data?

  10. 10

    How can I change the order of accessibility elements in a view controller without losing access to the navigation bar?

  11. 11

    How can I un-export a variable, without losing its value?

  12. 12

    How can I hide/show html elements without losing initial CSS Styling?

  13. 13

    How can I convert a drive from ext4 to NTFS without losing the data?

  14. 14

    How can I avoid nested Navigation Bars in SwiftUI?

  15. 15

    How can I avoid running some tests in parallel?

  16. 16

    How can I avoid Phusion Passenger running as root?

  17. 17

    How can I avoid using 'at' in radial-gradient?

  18. 18

    How can i avoid Jquery translate `?` to `%3F`

  19. 19

    How can I avoid overwriting dynamodb from two lambdas?

  20. 20

    EXC_BAD_ACCESS - How can I avoid it?

  21. 21

    How can i avoid or pass over a directory that is access denied?

  22. 22

    How can I avoid repeating the css and not using !important?

  23. 23

    How can I avoid a black background when fading in an overlay with ffmpeg?

  24. 24

    Can I avoid mutating in this scenario?

  25. 25

    Can i have ubuntu on SSD and WIndows on HDD without losing fils?

  26. 26

    Can I downgrade Vscode without losing my extensions?

  27. 27

    How can I avoid my program to keep running when I close my main frame?

  28. 28

    How can I avoid Firefox's "you have chosen to open" dialog when I try to download a file?

  29. 29

    Can I avoid nested namespaces in forward declaration?

ホットタグ

アーカイブ