How to control the number of decimals places for display purpose only using Image function in Ada?

Viewed 454

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.
4 Answers

’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

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"

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);

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.

Related