Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2014-04

Inconsistent results currency - extended ?

10 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

LacaK

Hi,
I catch strange behavior, which I can not understand ;-)

I have 2 PC on both I have installed Lazarus 1.2.2 + FPC 2.6.4 (official release)

1st PC has Windows 98 2nd PC has Windows Vista (32 bit)

I have this program:
=============================
var
  c: currency;
  e: extended;
begin
  c:=-92233720368547;
  e:=c;
  writeln('CW=', Get8087cw(), ' currency=', c, ' extended=', e, '
string=', currtostr(c));
=============================

When I compile on 1st PC (Win98) and run it on 1st or 2nd PC I get this result:
CW=4978 currency=-9.223372036854699520E+13
extended=-9.2233720368546995E+0013 string=-92233720368546,9952

When I compile on 2nd PC (Win Vista) and run on 1st or 2nd PC I get (expected) result:
CW=4978 currency=-9.223372036854700000E+13
extended=-9.2233720368547000E+0013 string=-92233720368547

How is it possible?
Is compiled code somehow affected by platform on which is compilation performed?

Thanks
-Laco.

Reply by email

Pierre Free Pascal
to LacaK: I catch strange behavior, which I can not understand ;-) I have 2 PC on both I have…

Your code does not even compile on
my 2.6.4 installation (no Lazarus).

Where does the currtostr function come from?
Apparently from sysutils unit.
How is it 'included' without any uses clause?
I found no option that automatic
add unit sysutils.

Could you give us a source and a compilation command line that does not require Lazarus use?

Pierre Muller

Show quoted text 48 lines
-----Message d'origine----- De : [mailto:fpc-pascal- De la part de LacaK Envoyé : mardi 29 avril 2014 10:23 À : FPC-Pascal users discussions Objet : [fpc-pascal] Inconsistent results currency - extended ? Hi, I catch strange behavior, which I can not understand ;-) I have 2 PC on both I have installed Lazarus 1.2.2 + FPC 2.6.4 (official release) 1st PC has Windows 98 2nd PC has Windows Vista (32 bit) I have this program: ============================= var c: currency; e: extended; begin c:=-92233720368547; e:=c; writeln('CW=', Get8087cw(), ' currency=', c, ' extended=', e, ' string=', currtostr(c)); ============================= When I compile on 1st PC (Win98) and run it on 1st or 2nd PC I get this result: CW=4978 currency=-9.223372036854699520E+13 extended=-9.2233720368546995E+0013 string=-92233720368546,9952 When I compile on 2nd PC (Win Vista) and run on 1st or 2nd PC I get (expected) result: CW=4978 currency=-9.223372036854700000E+13 extended=-9.2233720368547000E+0013 string=-92233720368547 How is it possible? Is compiled code somehow affected by platform on which is compilation performed? Thanks -Laco. _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

LacaK
to Pierre Free Pascal
Show quoted text 6 lines
Your code does not even compile on my 2.6.4 installation (no Lazarus). Where does the currtostr function come from? Apparently from sysutils unit.

Yes from SysUtils

Show quoted text 7 lines
How is it 'included' without any uses clause? I found no option that automatic add unit sysutils. Could you give us a source and a compilation command line that does not require Lazarus use?

Source code attached.
Command line parameters: -MObjFPC -Scghi -O1 -Twin32 -Pi386 -g -gl -vewnhi -Filib\i386-win32 -Fu. -FUlib\i386-win32 -l (taken from Lazarus as I never have used only standalone compiler , without Lazarus IDE)

========= PROGRAM ==============
program test_Currency;
{$mode objfpc}{$H+}
uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  SysUtils;
var
  s: string;
  c: currency;
  e: extended;
  d: double;
  i64: int64;
begin
  c:=-92233720368547;
  d:=-92233720368547;
  e:=c;
  i64:=PInt64(@c)^;
  writeln('CW=', Get8087cw());
  writeln('currency=', c);
  writeln('extended=', e);
  writeln('string=', currtostr(c));
  writeln('int64=', i64);
  writeln('double=', d);
  readln;
end.
================================

When I compile on Win98 and run (it does not depend if it is ran on Win98 or XP or Vista) output is same:
=========== OUTPUT 1 ===========
CW=4978
currency=-9.223372036854699520E+13
extended=-9.2233720368546995E+0013
string=-92233720368546,9952
int64=-922337203685469952
double=-9.22337203685470E+013
================================
It seems (based on "i64" variable), that currency "c" is wrong initialised with "-92233720368546.9952"
On other side double is correct "-92233720368547"

When I compile on Win Vista and run (it does not depend if it is Win98 or XP or Vista) output is correct (as expected):
=========== OUTPUT 2 ============
CW=4978
currency=-9.223372036854700000E+13
extended=-9.2233720368547000E+0013
string=-92233720368547
int64=-922337203685470000
double=-9.22337203685470E+013
================================

Thanks
-Laco.

Show quoted text 58 lines
Pierre Muller > -----Message d'origine----- > De : [mailto:fpc-pascal- > De la part de LacaK > Envoyé : mardi 29 avril 2014 10:23 > À : FPC-Pascal users discussions > Objet : [fpc-pascal] Inconsistent results currency - extended ? > > Hi, > I catch strange behavior, which I can not understand ;-) > > I have 2 PC on both I have installed Lazarus 1.2.2 + FPC 2.6.4 > (official > release) > > 1st PC has Windows 98 2nd PC has Windows Vista (32 bit) > > I have this program: > ============================= > var > c: currency; > e: extended; > begin > c:=-92233720368547; > e:=c; > writeln('CW=', Get8087cw(), ' currency=', c, ' extended=', e, ' > string=', currtostr(c)); > ============================= > > When I compile on 1st PC (Win98) and run it on 1st or 2nd PC I get this > result: > CW=4978 currency=-9.223372036854699520E+13 > extended=-9.2233720368546995E+0013 string=-92233720368546,9952 > > When I compile on 2nd PC (Win Vista) and run on 1st or 2nd PC I get > (expected) result: > CW=4978 currency=-9.223372036854700000E+13 > extended=-9.2233720368547000E+0013 string=-92233720368547 > > How is it possible? > Is compiled code somehow affected by platform on which is compilation > performed? > > Thanks > -Laco. > > _______________________________________________ > fpc-pascal maillist - > http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal > _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

Bruno Krayenbuhl
to LacaK: I catch strange behavior, which I can not understand ;-) I have 2 PC on both I have…

Tested with FPC 2.6.4 .

LacaK are you sure you compile with the same version.

To me everything looks fine.

program test_Currency;
{$mode objfpc}{$H+}
uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  SysUtils;
var
  s: string;
  c: currency;
  e: extended;
  d: double;
  i64: int64;
begin
  i64:=1 shl 63;
  c:=PCurrency(@i64)^; // Minimum representable currency
  d:=-922337203685479999;
  e:=c;
  i64:=PInt64(@c)^;
  writeln('CW=', Get8087cw());
  writeln('currency=', c);
  c:=-92233720368547.9999; // LacaK currency
  writeln('currency=', c);
  writeln('extended=', e);
  writeln('string=', currtostr(c));
  writeln('int64=', i64);
  writeln('double=', d);
  readln;
end.

Gives me :
CW=4978
currency=-9.223372036854775808E+14 -> Ok to me
currency=-9.223372036854799990E+13 -> Ok to me
extended=-9.2233720368547758E+0014
string=-92233720368547.9999 -> Ok to me
int64=-9223372036854775808
double=-9.22337203685480E+017

BrunoK

Reply by email

Bruno Krayenbuhl

Lacak :

1 - XP difference between 2.6.4 and 2.7.1 on same machine

    writeln('extended=', e);
    extended=-9.22337203685477580811E+0014   <== HERE
       calls str_real in real2str.inc that is in the course of beeing modified in 2.7.1. If your compare the source code, you will see it has changed and is in fact work in progress, at least in my OLD downloaded version of FPC2.7.1.

If it is still like that with the latest developpment 2.7.1, maybe some knowlegable developper should have a - Difference between 2.6.4 on Win98 and WinXP. I suspect that these 2 are on different computers and thus do not have exactly the same floating point unit. Line

  e:=c; uses the FPU to convert from Currency to Extended. Schematically, Extended stores values Sign*2^exponent*Mantissa. (See http://en.wikipedia.org/wiki/Extended_precision for more info) That means, for example, that 0.1 cannot be EXACTLY stored in an Extended thus, depending on the FPU, they might be converted to a slightly different representation.

2b - Quote : It seems, that FPC on Win98 incorrectly stores currency constant. No. And the proof is that :

     writeln('currency=', c);
     writeln('string=', currtostr(c));
  do actualy writeln the correct result. Both use at some point currtostr(c). What currtostr(c) does is expand the Int64(c) to a decimal string and then insert the point in the position(length-4).

As long as there are no divisions and no Overflow, Currency will give correct and exact decimal results in all +, -,* computations, it is a simple Int64 that is converted (see 2b) to a decimal representation when displayed. I have used Currency in Quick Basic Compiler in the old days, then in Delphi applications for accounting purposes (with some customized roundings / convertions to Float when needed) and never had complaints from users.

Regards, Bruno

Reply by email

LacaK
to Bruno Krayenbuhl

Bruno Krayenbuhl wrote / napísal(a):

2 - Difference between 2.6.4 on Win98 and WinXP. I suspect that these 2 are on different computers and thus do not have exactly the same floating point unit.

Yes Win 98 is on PC with Intel Pentium 4 CPU and Win XP on PC with Intel Core 2 Duo CPU

But lets look again at our "simplified" program:
=========================
var

  c: currency;
  i64: int64;

begin

  c:=92233720368547;

=========================
Here I stop and let's look at assembler of "c:=92233720368547" : --------------------------------------
00401543 a1c0204100 mov 0x4120c0,%eax // low 4 bytes; EAX=-859001088 resp. 0xccccaf00 = 3435966208 00401548 a300604100 mov %eax,0x416000 0040154D a1c4204100 mov 0x4120c4,%eax // high 4 bytes; EAX=214748364
00401552 a304604100 mov %eax,0x416004 --------------------------------------
So currency value is: 2^32*214748364 + 3435966208 = 922337200249503744 + 3435966208 = 922337203685469952
Not as expected 922337203685470000 !
(this is on Win 98 PC !, on Win XP PC are values in EAX correct 3435966256, 214748364)

So constant "92233720368547" which is part of generated EXE (I think) is wrong parsed or interpreted or what and stored wrongly in output EXE file. But why it happens ? What part of compiler is responsible for parsing constants in source code and translating them to binary form in which is stored in output EXE file ?
Does compiler links any external DLLs which probably may change FPU control word (precision or so) ?
Does compiler first converts value to floating point representation ant then back to currency or ?

Thanks
-Laco.

Reply by email

Bruno Krayenbuhl
to LacaK

My point N°2 regarding potential FPU difference was only concerning instruction line

  e:=c;

=========================

I have absolutely no idea of how the compiler does translate Currency constant to code, sorry.

May be it uses the FPU when translating from String representation to assembler value, but I have absolutely no idea where that would be done in the compiler.

Anyway, it may be possible that the compiler uses StrToCurr or something similar.

var cAsString:string;
.
.
cAsString:=CurrToStr(c);
c:=StrToCurr(cAsString). { <== Check after here on W98 / XP and look for differences on value c.  That uses an FPU instruction fistpll that look as causing some trouble to other projects (Non FPC) }

.
.

Regards, Bruno

Note : I'm interested to know what you discover since I like using Currency's var.

Reply by email

LacaK
to Bruno Krayenbuhl

Bruno Krayenbuhl wrote / napísal(a):

Show quoted text 18 lines
I have absolutely no idea of how the compiler does translate Currency constant to code, sorry. May be it uses the FPU when translating from String representation to assembler value, but I have absolutely no idea where that would be done in the compiler. Anyway, it may be possible that the compiler uses StrToCurr or something similar. var cAsString:string; . . cAsString:=CurrToStr(c); c:=StrToCurr(cAsString). { <== Check after here on W98 / XP and look for differences on value c. That uses an FPU instruction fistpll that look as causing
For :
  c:=strtocurr('92233720368547');
  writeln(c); // here I get CORRECT result: 9.223372036854700000E+13
But as I wrote:
  c:=92233720368547;
  writeln(c);  // here I get INCORRECT result: 9.223372036854699520E+13

But as I wrote it is not a problem of displaying currency value, it is problem that currency variable realy contains incorrect number, which is then correctly displayed ... ;-(

-Laco.

Reply by email