Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Precision of reals through writeln/readln in Delphi

My clients application exports and imports quite a few variables of type real through a text file using writeln and readln. I've tried to increase the width of the fields written so the code looks like:

writeln(file, exportRealvalue:30); //using excess width of field
....
readln(file, importRealvalue);

When I export and then import and export again and compare the files I get a difference in the last two digits, e.g (might be off on the actual number of digits here but you get it):

-1.23456789012E-0002
-1.23456789034E-0002

This actually makes a difference in the app so the client wants to know what I can do about it. Now I'm not sure it's only the write/read that does it but I thought I'd throw a quick question out there before I dive into the hey stack again. Do I need to go binary on this?

This is not an app dealing with currency or something, I just write and read the values to/from file. I know floating points are a bit strange sometimes and I thought one of the routines (writeln/readln) may have some funny business going on.

like image 467
Niklas Winde Avatar asked Nov 17 '25 21:11

Niklas Winde


1 Answers

You might try switching to extended for greater precision. As was pointed out though, floating point numbers only have so many significant digits of precision, so it is still possible to display more digits then are accurately stored, which could result in the behavior you specified.

From the Delphi help:

Fundamental Win32 real types

                                            | Significant | Size in 
Type     | Range                            | digits      | bytes
---------+----------------------------------+-------------+----------
Real     | -5.0 x 10^–324 .. 1.7 x 10^308   | 15–16       |   8  
Real48   | -2.9 x 10^–39 .. 1.7 x 10^38     | 11-12       |   6   
Single   | -1.5 x 10^–45 .. 3.4 x 10^38     |  7-8        |   4   
Double   | -5.0 x 10^–324 .. 1.7 x 10^308   | 15-16       |   8   
Extended | -3.6 x 10^–4951 .. 1.1 x 10^4932 | 10-20       |  10   
Comp     | -2^63+1 .. 2^63–1                | 10-20       |   8   
Currency | -922337203685477.5808..          |             | 
                    922337203685477.5807    | 10-20       |   8   

Note: The six-byte Real48 type was called Real in earlier versions of Object Pascal. If you are recompiling code that uses the older, six-byte Real type in Delphi, you may want to change it to Real48. You can also use the {$REALCOMPATIBILITY ON} compiler directive to turn Real back into the six-byte type. The following remarks apply to fundamental real types.

  • Real48 is maintained for backward compatibility. Since its storage format is not native to the Intel processor architecture, it results in slower performance than other floating-point types.
  • Extended offers greater precision than other real types but is less portable. Be careful using Extended if you are creating data files to share across platforms.

Notice that the range is greater then the significant digits. So you can have a number larger then can be accurately stored. I would recommend rounding to the significant digits to prevent that from happening.

like image 73
Jim McKeeth Avatar answered Nov 20 '25 12:11

Jim McKeeth



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!