3

I have the following code line in Ada,

     Put_Line ("Array of " & Integer'Image (iterations)
        & "          is " & Long_Float'Image (sum) 
        & " Time = " & Duration'Image(milliS) & timescale);  

The number of decimal places in sum is too long for display (not for calculations since long float is needed for sum calculations). I know that Ada has alternative way of displaying decimals using aft and fore without using the Image function but before I switch to alternative I would like to know if Image has options or other technique of displaying decimals. Does Image function has an option to display decimals? Is there a technique to shorten the number of decimal places of the Long_Float for display only?

with Ada.Numerics;
 with Ada.Text_IO; use Ada.Text_IO;

 procedure Images is
 sum                : Standard.Long_Float;
 Pi                 : Long_Float := Ada.Numerics.Pi;

  type Fixed is delta 0.001 range -1.0e6 .. 1.0e6;
  type NewFixed is range -(2 ** 31) .. +(2 ** 31 - 1);
  type Fixed2 is new Long_Float range -1.0e99.. 1.0e99;
  type Fixed3 is new Long_Float range -(2.0e99) .. +(2.0e99);


 begin
 sum:=4.99999950000e14;
 Put_Line ("no fixing number: " & Pi'Image);
 Put_Line (" fixed number: " & Fixed'Image(Fixed (Pi)));
 Put_Line ("no fixing number: " & Long_Float'Image(sum));
 Put_Line (" testing fix: " & Fixed3'Image(Fixed3 (sum)));
 end Images;

Addendum:

  1. Note that my variable sum is defined as Standard.Long_Float to agree with other variables used throughout the program.
  2. I am adding code to show the culprit of my problem and my attempts at solving the problem. It is based on example provided by Simon Wright with sum number added by me. Looks like all I need to figure out how to insert delta into Fixed3 type since delta defines number of decimals.
double-beep
  • 5,031
  • 17
  • 33
  • 41
Aschoolar
  • 343
  • 3
  • 9

4 Answers4

6

’Image doesn’t have any options, see ARM2012 3.5(35) (also (55.4)).

However, Ada 202x ARM K.2(88) and 4.10(13) suggest an alternative:

with Ada.Numerics;
with Ada.Text_IO; use Ada.Text_IO;
procedure Images is
   Pi : Long_Float := Ada.Numerics.Pi;
   type Fixed is delta 0.001 range -1.0e6 .. 1.0e6;
begin
   Put_Line (Pi'Image);
   Put_Line (Fixed (Pi)'Image);
end Images;

which reports (GNAT CE 2020, FSF GCC 10.1.0)

$ ./images 
 3.14159265358979E+00
 3.142
Simon Wright
  • 25,108
  • 2
  • 35
  • 62
  • Your approach was interesting. Unfortunately it does not build on my system. I am getting the error for`Put_Line(Fixed (Pi) 'Image);` which is the : `images.adb:8:14: prefix of "Image" attribute must be a type` It does not recognize the type that was defined by user. – Aschoolar Mar 24 '21 at 12:38
  • Okay, so far I managed to fix your example by changing this code line `Put_Line (Fixed (Pi)'Image);` into this code line `Put_Line (Fixed'Image(Fixed (Pi)));` – Aschoolar Mar 24 '21 at 13:34
  • Unfortunately, it does not work on my code. I think I know why. My sum value is about 4.99995000000E14 which is outside the range of exponent defined in Fixed type. It passed the build and compile command however it crashes in run time. I am getting error in execution time of the code at the line when it is supposed to print sum `raised CONSTRAINT_Error: code.adb 287 overflow check failed` – Aschoolar Mar 24 '21 at 13:55
5

The Image attribute has the same parameters for all the types, so format cannot be specified. There are generic nested packages in Ada.Text_IO for handling I/O of numeric types. For your case you can instantiate Ada.Text_IO.Float_IO for Float or just use the built-in Ada.Float_Text_IO instance. You can then use the Put procedure to specify the format. There is an example in the Ada Standard:

    package Real_IO is new Float_IO(Real); use Real_IO;
    -- default format used at instantiation, Default_Exp = 3
    
    X : Real := -123.4567;  --  digits 8      (see 3.5.7)
    
    Put(X);  -- default format                            "–​1.2345670E+02"
    Put(X, Fore => 5, Aft => 3, Exp => 2);                -- "bbb–​1.235E+2"
    Put(X, 5, 3, 0);                                      -- "b–​123.457"

Gneuromante
  • 560
  • 3
  • 12
  • Wow, syntax-highlighting is totally broken here for Ada. I've reached to https://meta.stackoverflow.com/questions/289919/can-we-add-ada-syntax-highlight and it could be improved using vhdl, but in fact the current highlighter supports Ada, so where is the problem? – Gneuromante Mar 23 '21 at 20:19
  • This example works for Standard.Float but not for Long_Float. – Aschoolar Mar 24 '21 at 12:43
  • In what sense? This works perfect for me, just the default format is different from Float: ``` with Ada.Text_IO; procedure Main is package Real_IO is new Ada.Text_IO.Float_IO(Long_Float); use Real_IO; X : Long_Float := -123.4567; -- digits 8 (see 3.5.7) begin Put(X); -- default format "–​1.2345670E+02" Put(X, Fore => 5, Aft => 3, Exp => 2); -- "bbb–​1.235E+2" Put(X, 5, 3, 0); -- "b–​123.457" end Main; ``` – Gneuromante Mar 24 '21 at 22:41
2

Long_Float'Image (sum) is just a regular string in the form "snnnnn.ddddd". Note that character 's' representing sign, character 'n' representing number and character 'd' representing decimal.

Thus, if you want to drop the last three decimals, just use the following

Long_Float'Image(sum)(Long_Float'Image(sum)'First .. Long_Float'Image(sum)'Last - 3);

Anh Vo
  • 149
  • 1
  • 3
  • That’s going to drop most of the exponent! – Simon Wright Mar 23 '21 at 17:54
  • Thats a nice trick for this particular problem. Like @SimonWright pointed out, my sum has E+05 at the end so the usage is limited. – Aschoolar Mar 24 '21 at 12:41
  • To @Anh Vo, I wonder if I can work around on your solution. Let say I take the First 6 digits and Last 3 digits and combine them. Can it be done. It also has some limitations. – Aschoolar Mar 24 '21 at 13:27
1

As others have pointed out, the 'Image attribute function doesn't provide for any control over the format. However, it is certainly possible to write a function that does. See PragmARC.Images.Float_Image for a generic example.

Jeffrey R. Carter
  • 3,033
  • 9
  • 10