Recent

Author Topic: floating point literals  (Read 3812 times)

srvaldez

  • Full Member
  • ***
  • Posts: 117
Re: floating point literals
« Reply #15 on: February 20, 2024, 06:44:15 pm »
a feature request then is to have typed literals.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5759
  • Compiler Developer
Re: floating point literals
« Reply #16 on: February 20, 2024, 09:17:06 pm »
a feature request then is to have typed literals.

No, because you can already type them by typecasting them.

srvaldez

  • Full Member
  • ***
  • Posts: 117
Re: floating point literals
« Reply #17 on: February 20, 2024, 09:34:20 pm »
well ok, but I am an advocate for unambiguous code AKA pedantic code, why leave something to guesswork?
yes, you can cast constants but in my opinion a simple postfix symbol is easier both to type and to read

xixixi

  • New Member
  • *
  • Posts: 25
Re: floating point literals
« Reply #18 on: February 20, 2024, 09:42:21 pm »
Alternatively, a different exponent marker, as in Lisp:

1e0 - real
1d0 - double
1f0 - single

PascalDragon

  • Hero Member
  • *****
  • Posts: 5759
  • Compiler Developer
Re: floating point literals
« Reply #19 on: February 20, 2024, 09:49:14 pm »
yes, you can cast constants but in my opinion a simple postfix symbol is easier both to type and to read

There is no need for some kind of postfix symbol, because the type casting already exists. We tend to avoid implementing multiple ways to express the same functionality except when required for compatibility to specific language dialect.

Alternatively, a different exponent marker, as in Lisp:

1e0 - real
1d0 - double
1f0 - single

No, see above.

explainedd

  • New Member
  • *
  • Posts: 11
Re: floating point literals
« Reply #20 on: February 20, 2024, 11:00:24 pm »
The typecast is the most clear (and verbose) solution for a few values.
It is possible to PUSH/POP the $MINFPCONSTPREC for larger code blocks:

Code: Pascal  [Select][+][-]
  1. {$MODE DELPHI}
  2. program demoFP;
  3.  
  4. type TestValue = packed record
  5.     case uint64 of
  6.         0: (doubleRepresentation: double);
  7.         1: (UInt64Representation: uint64);
  8. end;
  9.  
  10. var
  11.     tv: TestValue;
  12.     d: double;
  13.  
  14. begin
  15.     d := 1.0 / 3.0;
  16.     tv.doubleRepresentation := d;
  17.     writeln('                    single / single :', tv.UInt64Representation);
  18.  
  19.     d := Double(1.0) / Double(3.0);
  20.     tv.doubleRepresentation := d;
  21.     writeln('casted to double / casted to double :', tv.UInt64Representation);
  22.  
  23.     {$IFDEF FPC}{$PUSH}{$MINFPCONSTPREC 64}{$ENDIF}
  24.     d := 1.0 / 3.0;
  25.     {$IFDEF FPC}{$POP}{$ENDIF}
  26.     tv.doubleRepresentation := d;
  27.     writeln('                    double / double :', tv.UInt64Representation);
  28. end.
  29.  

PascalDragon

  • Hero Member
  • *****
  • Posts: 5759
  • Compiler Developer
Re: floating point literals
« Reply #21 on: February 23, 2024, 10:32:03 pm »
It is possible to PUSH/POP the $MINFPCONSTPREC for larger code blocks:

$MINFPCONSTPREC is not part of the settings that is (re)stored by $PUSH/$POP.

Thaddy

  • Hero Member
  • *****
  • Posts: 16196
  • Censorship about opinions does not belong here.
Re: floating point literals
« Reply #22 on: February 23, 2024, 11:02:36 pm »
It is also hardly documented, but in my view should be a local.
If I smell bad code it usually is bad code and that includes my own code.

explainedd

  • New Member
  • *
  • Posts: 11
Re: floating point literals
« Reply #23 on: February 24, 2024, 03:44:43 pm »
The documentation seems clear to me.

In Free Pascal Programmer’s Guide:
https://downloads.freepascal.org/fpc/docs-pdf/prog.pdf

$MINFPCONSTPREC is listed under Local directives.

$POP and $PUSH says:
Global settings (search paths etc.) are not saved/restored by this directive.

If I replace {$MINFPCONSTPREC 64} with {$APPTYPE GUI} (a global one), I get the following message:
demo_fp_02.pas(23,25) Warning: Misplaced global compiler switch, ignored

Here is a simple test to check $POP:
Code: Pascal  [Select][+][-]
  1. {$MODE DELPHI}
  2. program demoFP;
  3.  
  4. type TestValue = packed record
  5.     case byte of
  6.         0: (doubleRepresentation: double);
  7.         1: (UInt64Representation: uint64);
  8. end;
  9.  
  10. var
  11.     tv: TestValue;
  12.     d: double;
  13.  
  14. begin
  15.     d := 1.0 / 3.0;
  16.     tv.doubleRepresentation := d;
  17.     writeln('                    single / single :', tv.UInt64Representation);
  18.  
  19.     d := Double(1.0) / Double(3.0);
  20.     tv.doubleRepresentation := d;
  21.     writeln('casted to double / casted to double :', tv.UInt64Representation);
  22.  
  23.     {$IFDEF FPC}{$PUSH}{$MINFPCONSTPREC 64}{$ENDIF}
  24.     d := 1.0 / 3.0;
  25.     {$IFDEF FPC}{$POP}{$ENDIF}
  26.     tv.doubleRepresentation := d;
  27.     writeln('                    double / double :', tv.UInt64Representation);
  28.  
  29.     d := 1.0 / 3.0;
  30.     tv.doubleRepresentation := d;
  31.     writeln('Single type again:  single / single :', tv.UInt64Representation);
  32. end.
  33.  

The results:

                    single / single :4599676419600023552
casted to double / casted to double :4599676419421066581
                    double / double :4599676419421066581
Single type again:  single / single :4599676419421066581


Still double / double.

This gives back the single/single result:
Code: Pascal  [Select][+][-]
  1. {$MODE DELPHI}
  2. program demoFP;
  3.  
  4. type TestValue = packed record
  5.     case byte of
  6.         0: (doubleRepresentation: double);
  7.         1: (UInt64Representation: uint64);
  8. end;
  9.  
  10. var
  11.     tv: TestValue;
  12.     d: double;
  13.  
  14. begin
  15.     d := 1.0 / 3.0;
  16.     tv.doubleRepresentation := d;
  17.     writeln('                    single / single :', tv.UInt64Representation);
  18.  
  19.     d := Double(1.0) / Double(3.0);
  20.     tv.doubleRepresentation := d;
  21.     writeln('casted to double / casted to double :', tv.UInt64Representation);
  22.  
  23.     {$MINFPCONSTPREC 64}
  24.     d := 1.0 / 3.0;
  25.     {$MINFPCONSTPREC DEFAULT}
  26.     tv.doubleRepresentation := d;
  27.     writeln('                    double / double :', tv.UInt64Representation);
  28.  
  29.     d := 1.0 / 3.0;
  30.     tv.doubleRepresentation := d;
  31.     writeln('Single type again:  single / single :', tv.UInt64Representation);
  32. end.
  33.  

Some clarification needed in the documentation.

Thanks PascalDragon

explainedd

  • New Member
  • *
  • Posts: 11
Re: floating point literals
« Reply #24 on: February 24, 2024, 04:41:54 pm »
TRon,

A full list of supported settings by $PUSH / $POP would be nice.
How can I decide if a directive is supported by $PUSH / $POP?

TRon

  • Hero Member
  • *****
  • Posts: 3649
Re: floating point literals
« Reply #25 on: February 24, 2024, 04:56:20 pm »
TRon,

A full list of supported settings by $PUSH / $POP would be nice.
How can I decide if a directive is supported by $PUSH / $POP?
Sorry for having removed my post explainedd.

Basically I wrote that the directive only applies to/for declarations. But as explainedd's example shows, that is not entirely true and apparently undocumented

So the question as of which directives are supported by push/pop seem to be a legitimate one. The basic rule is, as I always assumed, for every local directive as documented:
Quote
The $PUSH directive saves the current values of all local compiler directives on the settings stack

Perhaps another push/pop related issue ?
« Last Edit: February 24, 2024, 04:57:56 pm by TRon »
This tagline is powered by AI (AI advertisement: Free Pascal the only programming language that matters)

Paolo

  • Hero Member
  • *****
  • Posts: 538
Re: floating point literals
« Reply #26 on: February 24, 2024, 05:18:04 pm »
@Kodezwerg

Quote
What kind of type is "1.0" from your point of view?
From my point of view it is first of all a float and there it begins with the "Single" type, "1.0" does fit into "Single" so compiler does treat it as such.

and What kind of type is "1" from your point of view?

and then, what is the rule ?

Code: Pascal  [Select][+][-]
  1. var
  2.   x, y : double;
  3. ...
  4.   x:=0.1;
  5.   y:=1.0/10.0;
  6.   if x=y then beep  //<-- never beep
  7.  
  8.   x:=0.1;
  9.   y:=1/10;
  10.   if x=y then beep  //<--- beep
  11.  
  12.  

fcu

  • Full Member
  • ***
  • Posts: 100
Re: floating point literals
« Reply #27 on: February 25, 2024, 02:11:14 pm »
@Kodezwerg

Quote
What kind of type is "1.0" from your point of view?
From my point of view it is first of all a float and there it begins with the "Single" type, "1.0" does fit into "Single" so compiler does treat it as such.

and What kind of type is "1" from your point of view?

and then, what is the rule ?

Code: Pascal  [Select][+][-]
  1. var
  2.   x, y : double;
  3. ...
  4.   x:=0.1;
  5.   y:=1.0/10.0;
  6.   if x=y then beep  //<-- never beep
  7.  
  8.   x:=0.1;
  9.   y:=1/10;
  10.   if x=y then beep  //<--- beep
  11.  
  12.  

seems gcc works the oposit way

Code: C  [Select][+][-]
  1. void beep(int i){
  2.   printf("Beep %d\n",i);
  3. }
  4.  
  5. double x,y;
  6. int main()
  7. {
  8.     x = 0.1;
  9.     y = 1.0/10.0;
  10.  
  11.     if (x == y) beep(1); // beep
  12.  
  13.     x= 0.1;
  14.     y= 1/10;
  15.  
  16.     if (x == y) beep(2); // no beep
  17.  
  18.     return 0;
  19. }
  20.  
  21.  

Paolo

  • Hero Member
  • *****
  • Posts: 538
Re: floating point literals
« Reply #28 on: February 25, 2024, 02:33:05 pm »
I really don't understand why "1" is considered different from "1.0". I like the suggestion to heve a way to size the literals, like suggested by xixixi and others.

nanobit

  • Full Member
  • ***
  • Posts: 165
Re: floating point literals
« Reply #29 on: February 25, 2024, 04:41:28 pm »

and then, what is the rule ?

Code: Pascal  [Select][+][-]
  1. var
  2.   x, y : double;
  3. ...
  4.   x:=0.1;
  5.   y:=1.0/10.0;
  6.   if x=y then beep  //<-- never beep
  7.  
  8.   x:=0.1;
  9.   y:=1/10;
  10.   if x=y then beep  //<--- beep
  11.  
  12.  

I don't know the example's settings, but one explanation could be:
Both operands (1.0, 10.0) are single-type (under {$MINFPCONSTPREC default})
which leads to single-precision operation under {$EXCESSPRECISION off} at compile time.
So the resulting y is less precise than x. This is how FPC currently works and looks to be improvable.
(1/10) has higher precision which could have different reasons.

 

TinyPortal © 2005-2018