Sign in Join

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

Mailing lists / fpc-pascal / 2017-08

Freepascal Floating Point Issue

38 messages · 15 people · –

Reply by email Subscribe to this list Your subscription

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

James Richters

I am having an issue with a simple floating point application. I am setting a variable to a specific value and immediately after I set it, it is not exactly what I set it to. Here's an example

   Draw_GX_Min:=999.999;
   Writeln(Draw_GX_Min:3:30);

The writeln results in 999.999000000000020000000000000000

Why is it not 999.999000000000000000000000000000 where did 0.00000000000002 come from?

Draw_GX_Min is defined as a Double. I don't need that much precision for any reason. I'm just trying to understand why it's not what I set it to.

The reason I noticed this is because I have some conditional statements like If Draw_GX_Min99.999 then
Something....

And sometimes they works as expected, and sometimes not. I realize I could do:

If round(Draw_GX_Min*1000)999999 then
   Something

and it would work, but why do I need to do this when I explicitly set it to 999.999?

Does anyone know what is going on here that would be kind enough to explain it to me?

I suspect this has something to do with floating point, but I don't really understand what's happening.

Is there a better way to define my variable, perhaps defined as fixed decimal point instead of allowing it to float.... so that say all numbers from -999.99999 to 999.99999 are guaranteed to be represented accurately to 5 decimal places so that if I set one to 999.99999 it would actually be 999.99999 exactly? I would rather have less precision but have variables retain exactly what they are set to, not something close

Thanks

James

Ralf Quint
to James Richters
James Richters wrote 9 lines
I am having an issue with a simple floating point application. I am setting a variable to a specific value and immediately after I set it, it is not exactly what I set it to. Here's an example Draw_GX_Min:=999.999; Writeln(Draw_GX_Min:3:30); The writeln results in 999.999000000000020000000000000000 Why is it not 999.999000000000000000000000000000 where did 0.00000000000002 come from?

Out of thin air... Well, kind of. Double floating point means 16 digits of precision, so when you force a 30 digit precision output, anything past 16 digits is random garbage, at best...

Ralf

---
This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus

Daniel Franzini
to Ralf Quint

It might be the case (I didn't do the math) that 999.999 doesn't have an exact representation in IEEE-754 double-precision format, so the best you get is an aproximation (a pretty good one, btw).

Ralf Quint wrote 27 lines
On 8/21/2017 3:02 PM, James Richters wrote: > I am having an issue with a simple floating point application. I am setting a variable to a specific value and immediately after I set it, it is not exactly what I set it to. Here's an example > > Draw_GX_Min:=999.999; > Writeln(Draw_GX_Min:3:30); > > The writeln results in 999.999000000000020000000000000000 > > Why is it not 999.999000000000000000000000000000 where did 0.00000000000002 come from? > Out of thin air... Well, kind of. Double floating point means 16 digits of precision, so when you force a 30 digit precision output, anything past 16 digits is random garbage, at best... Ralf --- This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Daniel "Let us change our traditional attitude to the construction of programs. Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do." (Donald Knuth) "Yes, technogeeks can be funny, even if only to each other." ( http://www.boogieonline.com/revolution/science/humor/)" "Man is driven to create; I know I really love to create things. And while I'm not good at painting, drawing, or music, I can write software." (Yukihiro Matsumoto, a.k.a. ``Matz'')
Ralf Quint
to Daniel Franzini
Daniel Franzini wrote
It might be the case (I didn't do the math) that 999.999 doesn't have an exact representation in IEEE-754 double-precision format, so the best you get is an aproximation (a pretty good one, btw).

Just use WriteLn (Draw_GX_Min:3:16) and you get no mystery digits anymore...

In pretty much any programming language/compiler, if you print more digits than the precision of the used variable defines, you will get random numbers after the defined precision.
This is not something FreePascal specific, any C/C++ compiler for example will do the same thing. People need to learn what limitations come along with floating point variables/calculations...

Ralf

---
This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus

Daniel Franzini
to Ralf Quint

Long story short: not every single real number have an *exact* representation in the computer. You have to live with that and learn the limitations and pitfalls of floating point calculations.

Ralf Quint wrote 24 lines
On 8/21/2017 3:34 PM, Daniel Franzini wrote: > It might be the case (I didn't do the math) that 999.999 doesn't have > an exact representation in IEEE-754 double-precision format, so the > best you get is an aproximation (a pretty good one, btw). Just use WriteLn (Draw_GX_Min:3:16) and you get no mystery digits anymore... In pretty much any programming language/compiler, if you print more digits than the precision of the used variable defines, you will get random numbers after the defined precision. This is not something FreePascal specific, any C/C++ compiler for example will do the same thing. People need to learn what limitations come along with floating point variables/calculations... Ralf --- This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Daniel "Let us change our traditional attitude to the construction of programs. Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do." (Donald Knuth) "Yes, technogeeks can be funny, even if only to each other." ( http://www.boogieonline.com/revolution/science/humor/)" "Man is driven to create; I know I really love to create things. And while I'm not good at painting, drawing, or music, I can write software." (Yukihiro Matsumoto, a.k.a. ``Matz'')
Sven Barth
to James Richters: I am having an issue with a simple floating point application. I am setting a variable…

Am 22.08.2017 00:02 schrieb "James Richters" <

:

The others already wrote about floating point precision, so I won't repeat that.

The reason I noticed this is because I have some conditional statements

like

If Draw_GX_Min99.999 then Something....

*DON'T* compare floating point numbers like that. Instead use SameValue() from the Math unit which has an additional epsilon value (with a default value) that defines a lower and upper bound from your desired value to compare to.

Regards,
Sven

Unknown author
to Sven Barth

https://www.facebook.com/notes/new-stanford-pascal-compiler/floating-point-output-differences-between-platforms/365845753799072 <https://www.facebook.com/notes/new-stanford-pascal-compiler/floating-point-output-differences-between-platforms/365845753799072> /

other Pascal Implementations have to provide solutions to this issue, too

Kind regards

Bernd

------------------------------------------------------------------------ Gesendet mit der Telekom Mail App
<http://www.t-online.de/service/redir/email_app_android_sendmail_footer.htm>

--- Original-Nachricht ---
Von: Sven Barth via fpc-pascal
Betreff: Re: [fpc-pascal] Freepascal Floating Point Issue Datum: 22.08.2017, 7:54 Uhr
An: FPC-Pascal users discussions
Cc: Sven Barth

Am 22.08.2017 00:02 schrieb "James Richters" <

:

The others already wrote about floating point precision, so I won't repeat that.

The reason I noticed this is because I have some conditional statements

like

If Draw_GX_Min99.999 then Something....

*DON'T* compare floating point numbers like that. Instead use SameValue() from the Math unit which has an additional epsilon value (with a default value) that defines a lower and upper bound from your desired value to compare to.

Regards,
Sven

Sven Barth
to Peter
"Peter" wrote 8 lines
Hi James, Its unlikely that 999.999 has an EXACT representation in floating point. 999.99900000000002 maybe the closest value at your chosen precision. Extended type has more precision, but still probably won't be exact.

Additionally Extended is not cross platform.

Regards,
Sven

Mark Morgan Lloyd
to Ralf Quint: Out of thin air... Well, kind of. Double floating point means 16 digits of precision, so…
Ralf Quint wrote
On 8/21/2017 3:02 PM, James Richters wrote:> I am having an issue with a simple floating point application. I am setting a variable to a specific value and immediately after I set it, it is not exactly what I set it to. Here's an example>> Draw_GX_Min:=999.999;> Writeln(Draw_GX_Min:3:30);>> The writeln results in 999.999000000000020000000000000000 >> Why is it not 999.999000000000000000000000000000 where did 0.00000000000002 come from?>Out of thin air... Well, kind of. Double floating point means 16 digitsof precision, so when you force a 30 digit precision output, anythingpast 16 digits is random garbage, at best...

And in any event, that's probably much more precision than the GPU is using to generate the final image :-)

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]
Ralf Quint
to Mark Morgan Lloyd
Mark Morgan Lloyd wrote 15 lines
On 21/08/17 22:15, Ralf Quint wrote: > On 8/21/2017 3:02 PM, James Richters wrote:> I am having an issue > with a simple floating point application.  I am setting a variable to > a specific value and immediately after I set it,  it is not exactly > what I set it to.  Here's an example>>    Draw_GX_Min:=999.999;>    > Writeln(Draw_GX_Min:3:30);>> The writeln results in > 999.999000000000020000000000000000  >> Why is it not  > 999.999000000000000000000000000000  where did 0.00000000000002 come > from?>Out of thin air... Well, kind of. Double floating point means > 16 digitsof precision, so when you force a 30 digit precision output, > anythingpast 16 digits is random garbage, at best... And in any event, that's probably much more precision than the GPU is using to generate the final image :-)

Well, older GPUs (at least NVidia, pretty sure similar restrictions apply to AMD) use(d) only 32bit "single" floats, giving a 7 digit precision, though newer ones can also handle 64bit doubles. But there are quite a few differences in how certain FP operations are handled on those GPUs, which result in even doubles only having 14 (instead of 16) digits of while NVidia keeps mentioning IEEE754,
their GPUs are in practice not 100% compliant.

As I mentioned before, if someone needs to work a lot with floating point arithmetic, it really helps to get yourself acquainted to the way those works and all the possible pitfalls.

Btw, anyone know about a BCD math implementation for Free Pascal, like it used to be implemented in DR CBASIC? (those were the days... ;-) )

Ralf

---
This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus

Paul Nance
to Ralf Quint

Turbo Pascal also had a BCD unit.

"Ralf Quint" wrote 42 lines
On 8/22/2017 1:39 PM, Mark Morgan Lloyd wrote: > On 21/08/17 22:15, Ralf Quint wrote: >> On 8/21/2017 3:02 PM, James Richters wrote:> I am having an issue >> with a simple floating point application. I am setting a variable to >> a specific value and immediately after I set it, it is not exactly >> what I set it to. Here's an example>> Draw_GX_Min:=999.999;> >> Writeln(Draw_GX_Min:3:30);>> The writeln results in >> 999.999000000000020000000000000000 >> Why is it not >> 999.999000000000000000000000000000 where did 0.00000000000002 come >> from?>Out of thin air... Well, kind of. Double floating point means >> 16 digitsof precision, so when you force a 30 digit precision output, >> anythingpast 16 digits is random garbage, at best... > > And in any event, that's probably much more precision than the GPU is > using to generate the final image :-) > Well, older GPUs (at least NVidia, pretty sure similar restrictions apply to AMD) use(d) only 32bit "single" floats, giving a 7 digit precision, though newer ones can also handle 64bit doubles. But there are quite a few differences in how certain FP operations are handled on those GPUs, which result in even doubles only having 14 (instead of 16) digits of while NVidia keeps mentioning IEEE754, their GPUs are in practice not 100% compliant. As I mentioned before, if someone needs to work a lot with floating point arithmetic, it really helps to get yourself acquainted to the way those works and all the possible pitfalls. Btw, anyone know about a BCD math implementation for Free Pascal, like it used to be implemented in DR CBASIC? (those were the days... ;-) ) Ralf --- This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Benito van der Zander
to Paul Nance
Btw, anyone know about a BCD math implementation for Free Pascal, like it used to be implemented in DR CBASIC? (those were the days... ;-) )

I have one here: http://benibela.de/sources_en.html#bigdecimalmath

Paul Nance wrote 61 lines
Turbo Pascal also had a BCD unit. On Aug 22, 2017 6:56 PM, "Ralf Quint" < > wrote: On 8/22/2017 1:39 PM, Mark Morgan Lloyd wrote: > On 21/08/17 22:15, Ralf Quint wrote: >> On 8/21/2017 3:02 PM, James Richters wrote:> I am having an issue >> with a simple floating point application. I am setting a variable to >> a specific value and immediately after I set it, it is not exactly >> what I set it to. Here's an example>> Draw_GX_Min:=999.999;> >> Writeln(Draw_GX_Min:3:30);>> The writeln results in >> 999.999000000000020000000000000000 >> Why is it not >> 999.999000000000000000000000000000 where did 0.00000000000002 come >> from?>Out of thin air... Well, kind of. Double floating point means >> 16 digitsof precision, so when you force a 30 digit precision output, >> anythingpast 16 digits is random garbage, at best... > > And in any event, that's probably much more precision than the GPU is > using to generate the final image :-) > Well, older GPUs (at least NVidia, pretty sure similar restrictions apply to AMD) use(d) only 32bit "single" floats, giving a 7 digit precision, though newer ones can also handle 64bit doubles. But there are quite a few differences in how certain FP operations are handled on those GPUs, which result in even doubles only having 14 (instead of 16) digits of while NVidia keeps mentioning IEEE754, their GPUs are in practice not 100% compliant. As I mentioned before, if someone needs to work a lot with floating point arithmetic, it really helps to get yourself acquainted to the way those works and all the possible pitfalls. Btw, anyone know about a BCD math implementation for Free Pascal, like it used to be implemented in DR CBASIC? (those were the days... ;-) ) Ralf --- This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus <https://www.avast.com/antivirus> _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal <http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal> _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Ralf Quint
to Benito van der Zander
Benito van der Zander wrote 5 lines
> Btw, anyone know about a BCD math implementation for Free Pascal, like > it used to be implemented in DR CBASIC? (those were the days... ;-) ) I have one here: http://benibela.de/sources_en.html#bigdecimalmath

Thanks, but that is not quite the same as having a BCD library for financial math. I will look though if that can be trimmed down into just that....

Ralf

---
This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus

Ralf Quint
to Paul Nance: Turbo Pascal also had a BCD unit.
Paul Nance wrote
Turbo Pascal also had a BCD unit.

Well, no, there was no unit, rather a version of Turbo Pascal 3.0x had a version that natively used BCD math for "reals" instead of the 6byte REAL type, just as there was a x87 version that used hardware x87 FP (IEEE754) floats instead of software emulated ones. That was at a time when the x87 processors where an addon to the basic CPU (8087 for the 8086/8088/80188, 80187 for the 808186, 80287 for 80286, 80387 for the 80386).

Ralf

---
This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus

James Richters
to Sven Barth: Am 22.08.2017 00:02 schrieb "James Richters" < The others already wrote about floating…

Thanks everyone for the explanation and solutions. I can work around it well enough now that I understand what’s happening, but I’m still curious if there is a way to define fixed point variables? In a C++ Project I was helping with recently, they had a way of defining a variable as having 2 places before the decimal and 30 places after? Since the decimal could never move (float) It ended up being much better defined. It’s like always moving the decimal over 30 places to the right, using integer math, then moving it back. I’m not sure if this was something the compiler did, or if maybe they had their own functions to do this… I had a difficult time following how things worked, but I do remember the fixed point variables. Anyway I thought I would just ask the question in case there is a way to define this in FreePascal

It seems to me that if you know you never need more than a fixed number of places before and after the decimal, then moving the decimal over the maximum number of places, performing integer math, which would round to the nearest integer(and cut off the useless garbage), then moving the decimal back would mean a fixed amount of precision with the benefit that one could do things like exact conditionals and get the expected result

James

Earlier message 20 lines
From: fpc-pascal On Behalf Of Sven Barth via fpc-pascal Sent: Tuesday, August 22, 2017 1:55 AM To: FPC-Pascal users discussions Cc: Sven Barth Subject: Re: [fpc-pascal] Freepascal Floating Point Issue Am 22.08.2017 00:02 schrieb "James Richters" < >: The others already wrote about floating point precision, so I won't repeat that. > The reason I noticed this is because I have some conditional statements like > If Draw_GX_Min99.999 then > Something.... *DON'T* compare floating point numbers like that. Instead use SameValue() from the Math unit which has an additional epsilon value (with a default value) that defines a lower and upper bound from your desired value to compare to. Regards, Sven
Sven Barth
to James Richters

Am 24.08.2017 14:00 schrieb "James Richters" <

: Thanks everyone for the explanation and solutions. I can work around it

well enough now that I understand what’s happening, but I’m still curious if there is a way to define fixed point variables? In a C++ Project I was helping with recently, they had a way of defining a variable as having 2 places before the decimal and 30 places after? Since the decimal could never move (float) It ended up being much better defined. It’s like always moving the decimal over 30 places to the right, using integer math, then moving it back. I’m not sure if this was something the compiler did, or if maybe they had their own functions to do this… I had a difficult time following how things worked, but I do remember the fixed point variables. Anyway I thought I would just ask the question in case there is a way to define this in FreePascal

They probably had a custom type with operator overloads and such for that which can be parameterized as a template with the amount of digits before and after the comma...

Somethings like that can be implemented in FPC as well, but the implementation would need to be done first at all ;)

Note: FPC (and Delphi) has a single fixed point type which is Currency. AFAIK it uses four digits after the comma and 28 in front of it.

Regards,
Sven

el es
to Sven Barth

On 24/08/17 13:26, Sven Barth via fpc-pascal wrote: [...]

Show quoted text 7 lines
Note: FPC (and Delphi) has a single fixed point type which is Currency. AFAIK it uses four digits after the comma and 28 in front of it. Regards, Sven

There was a project I remember, that I was told, for some e.g. tax purposes, 4 digits after the decimal point are not enough to round them properly... That is because, the calculation of e.g. VAT has to work out both ways (total=net+VAT and has to work out in every way, including when a bigger package is split into smaller units) and 4 decimal digits are not always enough to ensure this (and the program had to work internationally with all the different tax rules too) for arbitrarily large quantities, prices and tax bands.

I don't remember the exact details (it long time ago and couple of workplaces ago), of what they did, but the team developing it (in D7) was pretty stressed...

-l.

Ralf Quint
to Sven Barth: Free Pascal also has a BCD unit: FmtBCD. It provides a BCD type and operators as well…
Sven Barth wrote 9 lines
Am 23.08.2017 02:16 schrieb "Paul Nance" < >: > > Turbo Pascal also had a BCD unit. Free Pascal also has a BCD unit: FmtBCD. It provides a BCD type and operators as well operator overloads.

And where would such gem be hiding? It's not in neither my Lazarus 1.6/FPC 3.02 nor the Lazarus 1.8RC4/FPC 3.04 installs...

Ralf

---
This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus

Tomas Hajny
to Ralf Quint
Ralf Quint wrote 12 lines
On 8/24/2017 2:18 AM, Sven Barth via fpc-pascal wrote: > > Am 23.08.2017 02:16 schrieb "Paul Nance" < > >: > > > > Turbo Pascal also had a BCD unit. > > Free Pascal also has a BCD unit: FmtBCD. It provides a BCD type and > operators as well operator overloads. > And where would such gem be hiding? It's not in neither my Lazarus 1.6/FPC 3.02 nor the Lazarus 1.8RC4/FPC 3.04 installs...

Good point... It's in package rtl-objpas. I can see it included in the standard FPC 3.0.2 installation, but it's missing in 3.0.4 at the moment, because it got lost in the transition from fpcmake to fpmake apparently. Fortunately, that should be rather easy to fix. :-)

Tomas

Bernd Oppolzer
to el es: [...] There was a project I remember, that I was told, for some e.g. tax purposes, 4…
el es wrote 17 lines
On 24/08/17 13:26, Sven Barth via fpc-pascal wrote: [...] > Note: FPC (and Delphi) has a single fixed point type which is > Currency. AFAIK it uses four digits after the comma and 28 in front > of it. > > Regards, Sven > There was a project I remember, that I was told, for some e.g. tax purposes, 4 digits after the decimal point are not enough to round them properly... That is because, the calculation of e.g. VAT has to work out both ways (total=net+VAT and has to work out in every way, including when a bigger package is split into smaller units) and 4 decimal digits are not always enough to ensure this (and the program had to work internationally with all the different tax rules too) for arbitrarily large quantities, prices and tax bands. I don't remember the exact details (it long time ago and couple of workplaces ago), of what they did, but the team developing it (in D7) was pretty stressed...

When you do calculations of actual values of
on-board securities, you need 8 digits after the decimal point and more, because the stock quotation already has 6 digits after the decimal point, and you have to multiply that with the quantity, which has decimal parts, too.

With decimal arithmetic, rounded multiplication is pretty simple: you multiply the two items, giving a result with one decimal digit more as you need, then you round the result.

In PL/1:

    value = round (multiply (quantity, quotation, 15, 3), 2);

gives the rounded value in Euro, no matter how many digits after the decimal point quantity and quotation had. The multiply function will take care of the proper scaling and stop after the third digit which is sufficient to round at the second position.

Kind regards

Bernd

Show quoted text 5 lines
-l. _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Bernd Oppolzer
to James Richters: Thanks everyone for the explanation and solutions. I can work around it well enough now…
James Richters wrote 26 lines
Thanks everyone for the explanation and solutions.  I can work around it well enough now that I understand what’s happening, but I’m still curious if there is a way to define fixed point variables?  In a C++ Project I was helping with recently, they had a way of defining a variable as having 2 places before the decimal and 30 places after? Since the decimal could never move (float) It ended up being much better defined.   It’s like always moving the decimal over 30 places to the right, using integer math, then moving it back.  I’m not sure if this was something the compiler did, or if maybe they had their own functions to do this… I had a difficult time following how things worked, but I do remember the fixed point variables.  Anyway I thought I would just ask the question in case there is a way to define this in FreePascal It seems to me that if you know you never need more than a fixed number of places before and after the decimal, then moving the decimal over the maximum number of places, performing integer math, which would round to the nearest integer(and cut off the useless garbage), then moving the decimal back would mean a fixed amount of precision with the benefit that one could do things like exact conditionals and get the expected result James

IBM mainframes have decimal data types involving 31 decimal digits (maximum); the numbers of digits left and right of the decimal point may be chosen freely. The types are all compatible and promoted to floating point, when necessary. The mainframe languages, like PL/1 and COBOL, support them natively, and mainframe C, too:

    int x, y;
    decimal (15,2) amt;
    ...

These decimal data types are supported by the hardware (by machine instructions). This was an optional feature in the 1960s, but the modern machines of today all support it.

The decimal data is implemented as BCD data; hex digits are decimal digits, and a sign half byte is added, that makes 16 bytes for 31 digits. If shorter numbers are needed, less bytes are allocated (all lengths from 1 to 16 are supported). All decimal fields have odd numbers of digits.

I am thinking about adding support for decimal data in one of the next versions of my Stanford Pascal compiler, which targets this platform, as well as Windows, Linux, macOS etc.; of course, this decimal format will need to be emulated on the non-mainframe platforms.

For some years now, the mainframe also supports floating point data based on a decimal representation. But I don't have experience with this so far. Some compilers support this (PL/1).

Kind regards

Bernd

Ched
to Bernd Oppolzer

And under "modern" Windows, the extended type, which is fully supported by the FPU, is *degraded* to double. So, I can't do high precision computation with fpc even if the native hardware permits such computations. I'm glued to XP as the full capabilities of the FPU were on the hands of programmers, years ago.

Cheers, Ched'

Le 24.08.2017 à 21:31, Bernd Oppolzer a écrit :

Show quoted text 62 lines
Am 24.08.2017 um 14:00 schrieb James Richters: > > Thanks everyone for the explanation and solutions.  I can work around it well enough now that I > understand what’s happening, but I’m still curious if there is a way to define fixed point variables? > In a C++ Project I was helping with recently, they had a way of defining a variable as having 2 places > before the decimal and 30 places after? Since the decimal could never move (float) It ended up being > much better defined.   It’s like always moving the decimal over 30 places to the right, using integer > math, then moving it back.  I’m not sure if this was something the compiler did, or if maybe they had > their own functions to do this… I had a difficult time following how things worked, but I do remember > the fixed point variables.  Anyway I thought I would just ask the question in case there is a way to > define this in FreePascal > > It seems to me that if you know you never need more than a fixed number of places before and after the > decimal, then moving the decimal over the maximum number of places, performing integer math, which > would round to the nearest integer(and cut off the useless garbage), then moving the decimal back would > mean a fixed amount of precision with the benefit that one could do things like exact conditionals and > get the expected result > > James > > IBM mainframes have decimal data types involving 31 decimal digits (maximum); the numbers of digits left and right of the decimal point may be chosen freely. The types are all compatible and promoted to floating point, when necessary. The mainframe languages, like PL/1 and COBOL, support them natively, and mainframe C, too:    int x, y;    decimal (15,2) amt;    ... These decimal data types are supported by the hardware (by machine instructions). This was an optional feature in the 1960s, but the modern machines of today all support it. The decimal data is implemented as BCD data; hex digits are decimal digits, and a sign half byte is added, that makes 16 bytes for 31 digits. If shorter numbers are needed, less bytes are allocated (all lengths from 1 to 16 are supported). All decimal fields have odd numbers of digits. I am thinking about adding support for decimal data in one of the next versions of my Stanford Pascal compiler, which targets this platform, as well as Windows, Linux, macOS etc.; of course, this decimal format will need to be emulated on the non-mainframe platforms. For some years now, the mainframe also supports floating point data based on a decimal representation. But I don't have experience with this so far. Some compilers support this (PL/1). Kind regards Bernd _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Sven Barth
to Ched

Am 24.08.2017 23:46 schrieb "Ched" <

: And under "modern" Windows, the extended type, which is fully supported

by the FPU, is *degraded* to double. So, I can't do high precision computation with fpc even if the native hardware permits such computations. I'm glued to XP as the full capabilities of the FPU were on the hands of programmers, years ago.

Please note that this is only true for the 64-bit variants of Windows with 64-bit software. 32-bit software on those systems can use the FPU without any problems (in fact even 64-bit software can, but since Microsoft declared it as deprecated for the 64-bit mode it might happen in the future that it is no longer supported).

Regards,
Sven

Ralf Quint
to Ched: And under "modern" Windows, the extended type, which is fully supported by the FPU, is…
Ched wrote 5 lines
And under "modern" Windows, the extended type, which is fully supported by the FPU, is *degraded* to double. So, I can't do high precision computation with fpc even if the native hardware permits such computations. I'm glued to XP as the full capabilities of the FPU were on the hands of programmers, years ago.

It's not a problem of "modern" Windows, but a problem of any 64bit x86 OS that in that "long" mode the FPU does NOT support the extended data type (80 bits, 10 bytes). In 32bit mode, the FPU is using the "old" x87 FP unit on the chip, in 64bit mode, it is using the SSE FP unit, which doesn't have those 80 bit registers, it's 64 bit only (and several times faster).
So that you can use that with your Windows XP version is likely due to the fact that this is a 32bit version, not XP Professional 64 (or Windows Server 2003 64 for that matter).

There are apparently some ways to enable the FP calculation to use the x87 FPU and therefor the possibility of those 80 bit registers on Inter chips (so far), but for one, this runs significantly slower that the SSE FPU, and then this is apparently not supported by (all) AMD CPUs, so you are limiting yourself also on which systems your code can run...

Ralf

---
This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus

Sven Barth
to Ralf Quint
"Ralf Quint" wrote 22 lines
On 8/24/2017 2:45 PM, Ched wrote: > And under "modern" Windows, the extended type, which is fully > supported by the FPU, is *degraded* to double. So, I can't do high > precision computation with fpc even if the native hardware permits > such computations. I'm glued to XP as the full capabilities of the FPU > were on the hands of programmers, years ago. It's not a problem of "modern" Windows, but a problem of any 64bit x86 OS that in that "long" mode the FPU does NOT support the extended data type (80 bits, 10 bytes). In 32bit mode, the FPU is using the "old" x87 FP unit on the chip, in 64bit mode, it is using the SSE FP unit, which doesn't have those 80 bit registers, it's 64 bit only (and several times faster). So that you can use that with your Windows XP version is likely due to the fact that this is a 32bit version, not XP Professional 64 (or Windows Server 2003 64 for that matter). There are apparently some ways to enable the FP calculation to use the x87 FPU and therefor the possibility of those 80 bit registers on Inter chips (so far), but for one, this runs significantly slower that the SSE FPU, and then this is apparently not supported by (all) AMD CPUs, so you are limiting yourself also on which systems your code can run...

Plase note that all non-Windows 64-bit systems have no problems with enabling the FPU and even Windows needs to handle it due to 32-bit software requiring it.
The only x86_64 OS we support that doesn't have Extended enabled (by default) *is* Win64.

Regards,
Sven

Michael Schnell
to Benito van der Zander: I have one here: http://benibela.de/sources_en.html#bigdecimalmath
Benito van der Zander wrote
> Btw, anyone know about a BCD math implementation for Free Pascal, like > it used to be implemented in DR CBASIC? (those were the days... ;-) )

Why do BCD math if you need a predefined number of correct digits after the "point" and a "limited" count of digits before ?

Here you could do Int64 and consider a factor of 1/10^n. Would be a lot faster.

Seems like a candidate for type helper and overloading "*" and "div".

-Michael

Sven Barth
to Tomas Hajny: Good point... It's in package rtl-objpas. I can see it included in the standard FPC 3.0.2…
"Tomas Hajny" wrote 19 lines
On Thu, August 24, 2017 22:25, Ralf Quint wrote: > On 8/24/2017 2:18 AM, Sven Barth via fpc-pascal wrote: >> >> Am 23.08.2017 02:16 schrieb "Paul Nance" < >> >: >> > >> > Turbo Pascal also had a BCD unit. >> >> Free Pascal also has a BCD unit: FmtBCD. It provides a BCD type and >> operators as well operator overloads. >> > And where would such gem be hiding? It's not in neither my Lazarus > 1.6/FPC 3.02 nor the Lazarus 1.8RC4/FPC 3.04 installs... Good point... It's in package rtl-objpas. I can see it included in the standard FPC 3.0.2 installation, but it's missing in 3.0.4 at the moment, because it got lost in the transition from fpcmake to fpmake apparently. Fortunately, that should be rather easy to fix. :-)

Hmm? It's mentioned in both the trunk and the branches/fixes_3.0.0 rtl-objpas fpmake.pp file and that wasn't changed since the branch if 3.0.0. So when the unit is indeed missing in 3.0.4rc1 then that needs to be looked at.

Regards,
Sven

Tomas Hajny
to Sven Barth

On Fri, August 25, 2017 14:31, Sven Barth via fpc-pascal wrote: .
.

Show quoted text 10 lines
> Good point... It's in package rtl-objpas. I can see it included in the > standard FPC 3.0.2 installation, but it's missing in 3.0.4 at the > moment, > because it got lost in the transition from fpcmake to fpmake apparently. > Fortunately, that should be rather easy to fix. :-) Hmm? It's mentioned in both the trunk and the branches/fixes_3.0.0 rtl-objpas fpmake.pp file and that wasn't changed since the branch if 3.0.0. So when the unit is indeed missing in 3.0.4rc1 then that needs to be looked at.

Oops, sorry, you're right, it's there - I must have typed wrongly when searching for it. :-( In that case it should be in 3.0.4rc1 too (I'm on holiday with a limited connection, so I can't check it easily at the moment).

Tomas

Ched
to Michael Schnell: Supposedly of (m)any non-x64 archs as well. Hence relying on "extended" is not portable.…

Hello,

I agree that the extended type is not portable and not as fast as double.

But sometimes, we absolutely need numerical precision, so we have to assume the costs in terms of runtime and possibly nonportability. When the algorithms are nearly optimal, there is no room for software enhancement. So, the programmers, not the OS makers !, has to do the choices about accuracy, runtime and hardware configuration. For my numerical problems, I absolutely need "full" extended, not just doubles.

As the 18-19 digits extended type is availables in Freepascal for the common Intel processors, I don't understand why we will have no more the right to use it under x64 OS...

Cheers, Ched

Le 25.08.2017 à 08:08, Michael Schnell a écrit :

Show quoted text 14 lines
On 25.08.2017 01:32, Ralf Quint wrote: > > It's not a problem of "modern" Windows, but a problem of any 64bit x86 > OS Supposedly of (m)any non-x64 archs as well. Hence relying on "extended" is not portable. -Michael _______________________________________________ fpc-pascal maillist  -  http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Sven Barth
to Ched

Am 28.08.2017 00:32 schrieb "Ched" <

Show quoted text 7 lines
: Hello, I agree that the extended type is not portable and not as fast as double. But sometimes, we absolutely need numerical precision, so we have to

assume the costs in terms of runtime and possibly nonportability. When the algorithms are nearly optimal, there is no room for software enhancement. So, the programmers, not the OS makers !, has to do the choices about accuracy, runtime and hardware configuration. For my numerical problems, I absolutely need "full" extended, not just doubles.

As the 18-19 digits extended type is availables in Freepascal for the

common Intel processors, I don't understand why we will have no more the right to use it under x64 OS...

Because Microsoft declared it as deprecated. That means that should Microsoft ever bring out a 64-bit only OS they can simply disable the FPU handling in their kernel (e.g. saving the FPU state during a context switch) and then you are doomed and they did even warn you about this, cause they declared the x87 as deprecated from the beginning on Win64.

Regards,
Sven

Michael Schnell
to Sven Barth: Am 28.08.2017 00:32 schrieb "Ched" < assume the costs in terms of runtime and possibly…

On 28.08.2017 08:04, Sven Barth via fpc-pascal wrote:I don't understand why we will have no more the right to use it under x64 OS...

Because Microsoft declared it as deprecated. That means that should Microsoft ever bring out a 64-bit only OS ...

In fact this still is a (mere) portability problem. Supposedly in such a 64-bit only OS, 32 bit executables will not lose "extended" but will not be able to be fact I suppose there will be possibilities to run them in a virtual machine. E.g. Virtual Box already can build up an invisible "one window" virtual machine for a single running program.

-Michael

Florian Klaempfl
to Ched: And under "modern" Windows, the extended type, which is fully supported by the FPU, is…
Ched wrote
And under "modern" Windows, the extended type, which is fully supported by the FPU, is *degraded* to double. So, I can't do high precision computation with fpc even if the native hardware permits such computations.

FP permits it too, just recompile it with
FPC_SUPPORT_X87_TYPES_ON_WIN64. But be aware: MS might disable extended support at any time on 64 bit windows as the types are marked as deprecated.

Sven Barth
to Michael Schnell: On 28.08.2017 08:04, Sven Barth via fpc-pascal wrote:I don't understand why we will have…
"Michael Schnell" wrote
On 28.08.2017 08:04, Sven Barth via fpc-pascal wrote:I don't understand

why we will have no more the right to use it under x64 OS...

> > > Because Microsoft declared it as deprecated. That means that should

Microsoft ever bring out a 64-bit only OS ...

> In fact this still is a (mere) portability problem. Supposedly in such a

64-bit only OS, 32 bit executables will not lose "extended" but will not be able to be started at all.

In fact I suppose there will be possibilities to run them in a virtual

machine. E.g. Virtual Box already can build up an invisible "one window" virtual machine for a single running program.

The point here was if the FPU is used in a x64 process, which *is* possible, but disabled by default in the compiler.

Regards,
Sven