Recent

Author Topic: 'Rounding' to (say) 5 DP  (Read 3954 times)

tetrastes

  • Hero Member
  • *****
  • Posts: 761
Re: 'Rounding' to (say) 5 DP
« Reply #30 on: February 19, 2026, 10:28:23 pm »
What you call "binary" is actually "floating-point", and it's just one of many possible formats.
Actually floating point (and fixed point) can be binary, ternary, octal, decimal, hexadecimal, etc...

1/3 can be perfectly represented as a fraction.
Ah, your beloved fractions unit... May be it can calculate sin(1/3) as a fraction?
It's just a toy, there no any useful mathematics in it, not to say about performance. And it uses floating point, of course. May be I will try FloatToFraction(PI)...  :D

tetrastes

  • Hero Member
  • *****
  • Posts: 761
Re: 'Rounding' to (say) 5 DP
« Reply #31 on: February 20, 2026, 11:46:50 am »
Outputting to the Windows 10 and 11 console requires additional effort. 🔮

If you have Lazarus, you can simply add LazUTF8 to uses, and remove all that Windows stuff, and even {$codepage utf8}.
As a bonus your code becomes portable.

LV

  • Sr. Member
  • ****
  • Posts: 427
Re: 'Rounding' to (say) 5 DP
« Reply #32 on: February 20, 2026, 03:55:24 pm »
Outputting to the Windows 10 and 11 console requires additional effort. 🔮

If you have Lazarus, you can simply add LazUTF8 to uses, and remove all that Windows stuff, and even {$codepage utf8}.
As a bonus your code becomes portable.

I'm on Windows 11 and using
Lazarus 3.4 (rev lazarus_3_4) FPC 3.2.2 x86_64-win64-win32/win64
and
Lazarus 4.99 (rev 2386917088) FPC 3.3.1 x86_64-win64-win32/win64.

Suggestion from @tetrastes:

Code: Pascal  [Select][+][-]
  1. program test_tetrastes;
  2.  
  3. {$MODE OBJFPC}{$H+}
  4.  
  5. uses
  6.   SysUtils, LazUtf8;
  7.  
  8. function FloatToStrDot(x: Double; DP: Integer; const Sep: string): string;
  9. begin
  10.   Result := FloatToStrF(x, ffFixed, 18, DP);
  11.   Result := StringReplace(Result, '.', Sep, []);
  12. end;
  13.  
  14. begin
  15.   DefaultFormatSettings.DecimalSeparator := '.';
  16.   Writeln(FloatToStrDot(1.23456, 3, '·'));
  17.   Writeln(FloatToStrDot(1.23456, 3, '•'));
  18.   Writeln(FloatToStrDot(1.23456, 3, '∘'));
  19.   Writeln(FloatToStrDot(1.23456, 3, #128302));
  20.  
  21.   ReadLn;
  22. end.  
  23.  

Console output:

1·235
1235
1?235
1??235


My suggestion:

Code: Pascal  [Select][+][-]
  1. program test;
  2.  
  3. {$MODE OBJFPC}{$H+}
  4. {$codepage utf8}
  5.  
  6. uses
  7.   SysUtils, Windows;
  8.  
  9. function FloatToStrDot(x: Double; DP: Integer; const Sep: string): string;
  10. begin
  11.   Result := FloatToStrF(x, ffFixed, 18, DP);
  12.   Result := StringReplace(Result, '.', Sep, []);
  13. end;
  14.  
  15. begin
  16.   DefaultFormatSettings.DecimalSeparator := '.';
  17.   SetConsoleCP(CP_UTF8);
  18.   SetConsoleOutputCP(CP_UTF8);
  19.   SetMultiByteConversionCodePage(CP_UTF8);
  20.   SetTextCodePage(Output, CP_UTF8);
  21.   SetTextCodePage(Input, CP_UTF8);
  22.  
  23.   Writeln(FloatToStrDot(1.23456, 3, '·'));
  24.   Writeln(FloatToStrDot(1.23456, 3, '•'));
  25.   Writeln(FloatToStrDot(1.23456, 3, '∘'));
  26.   Writeln(FloatToStrDot(1.23456, 3, #128302));
  27.  
  28.   ReadLn;
  29. end.
  30.  

Console output:

1·235
1•235
1∘235
1🔮235


« Last Edit: February 20, 2026, 04:28:01 pm by LV »

J-G

  • Hero Member
  • *****
  • Posts: 992
Re: 'Rounding' to (say) 5 DP
« Reply #33 on: February 20, 2026, 04:02:38 pm »
It seems that I opened a can of worms that was better left sealed  %)

I had forgotten the issues associated with binary computers not actually being able to work with real word numbers  -  though being reminded does bring back many memories of thinking about working only in BCD   ;D   (which were quickly discounted!)

Having done a little more work - purely for the fun of it, the program already does more than originally intended; I've now found a further 'issue' that needs attention.

Initially, I wanted to give my grandson a reason to get interested in Trigonometry. I was amazed when he told me that he had never done ANY at school - so therefore even sin/cos/tan meant absolutely nothing to him. As he is looking to become an electrician he may well need (eventually) to have some understanding of at least the basics, so solving triangles would at least give him a grounding.

The program just takes any three of the six basic dimensions of a triangle and from those calculates the other three plus the area, perimeter & height.  All these can simply be displayed as 'figures' but I then added in a display of the Triangle 'style' - one of the 6 - Right, Isosceles, Equilatral . . . .  but now I'm adding Sin, Cos & Tan of all the angles - and here lies the new 'issue'  -   Tangent of 90º is  Infinity  -  certainly a number that is beyond normal representation, other than as a word - no doubt I could create a graphic of the recognised symbol but of course I still need to check for the particular exception.


FPC 3.0.0 - Lazarus 1.6 &
FPC 3.2.2  - Lazarus 2.2.0 
Win 7 Ult 64

tetrastes

  • Hero Member
  • *****
  • Posts: 761
Re: 'Rounding' to (say) 5 DP
« Reply #34 on: February 20, 2026, 08:34:54 pm »
@LV
Yes, you are right, my code doesn't work for characters which are not in the current console CP. I didn't check it.  :-[
In fact Middle Dot is presented in many console CP, and one need not utf8 to show it there.

EDIT. But your code changes CP to utf8 one (see attachment), you have to restore initial CP.
« Last Edit: February 20, 2026, 08:46:09 pm by tetrastes »

J-G

  • Hero Member
  • *****
  • Posts: 992
Re: 'Rounding' to (say) 5 DP
« Reply #35 on: March 02, 2026, 03:09:00 am »
I didn't anticipate returning to this topic but having done further work I've found an anomoly in the string-handling function kindly suggested by @WP.

viz : 
Code: Pascal  [Select][+][-]
  1. function WPFloatToStr(x: Double; Decs: Integer): String;
  2.   begin
  3.     Result := StringReplace(Format('%.*g', [Decs, x]), FormatSettings.DecimalSeparator, '·', []);
  4.   end;
  5.  

I call it 8 times from one procedure :
Code: Pascal  [Select][+][-]
  1.   procedure String_Dims;
  2.   begin
  3.     S_Dims[1].Dim := WPFloatToStr(S_Dims[1].Size,Deci);
  4.     S_Dims[2].Dim := WPFloatToStr(S_Dims[2].Size,Deci);
  5.     S_Dims[3].Dim := WPFloatToStr(S_Dims[3].Size,Deci);
  6.     S_Dims[4].Dim := WPFloatToStr(S_Dims[4].Size,Deci);
  7.     S_Dims[5].Dim := WPFloatToStr(S_Dims[5].Size,Deci);
  8.  
  9.     A_Dims[1].Dim := WPFloatToStr(A_Dims[1].Size,Deci);
  10.     A_Dims[2].Dim := WPFloatToStr(A_Dims[2].Size,Deci);
  11.     A_Dims[3].Dim := WPFloatToStr(A_Dims[3].Size,Deci);
  12.   end;
  13.  

The first 5 calls return the correct result with 5 DP (or whatever Deci is set to) but the last three always return 2 DP.

For clarity :
A_Dims[1].Size is 90 (so returns 90)
A_Dims[2].size is 53.130102354156 but returns  53.13
A_Dims[3].size is 36.869897645844 but returns  36.87

Both correct to 2DP but Deci is the same for all 8 calls.

Can anyone suggest why this might be?

Size is declared as 'single' and Dim is declared as 'String'
FPC 3.0.0 - Lazarus 1.6 &
FPC 3.2.2  - Lazarus 2.2.0 
Win 7 Ult 64

tetrastes

  • Hero Member
  • *****
  • Posts: 761

J-G

  • Hero Member
  • *****
  • Posts: 992
Re: 'Rounding' to (say) 5 DP
« Reply #37 on: March 02, 2026, 02:03:25 pm »
It seems you asked this already, and even found a decision:
https://forum.lazarus.freepascal.org/index.php/topic,73504.msg576757.html#msg576757

And also by @wp:
https://forum.lazarus.freepascal.org/index.php/topic,73504.msg576760.html#msg576760
D'Oh!  -  It seems that I should no longer be allowed anywhere near a RAD program unless accompanied by a 'carer'  :-[ :-[

Thanks for pulling me back to reality @tetrastes.

FPC 3.0.0 - Lazarus 1.6 &
FPC 3.2.2  - Lazarus 2.2.0 
Win 7 Ult 64

 

TinyPortal © 2005-2018