0

I do not have the ability to update our Ada compiler set so include the IEEE packages. Is there a way to convert a Float into a Hexadecimal integer? For instance, a Float value of 1.5 as input should yield an output of 3FC00000.

3 Answers 3

2

You can use Ada.Unchecked_Conversion for that job.

with Ada.Integer_Text_IO;
with Ada.Text_IO;
with Ada.Unchecked_Conversion;

procedure Main is
   Num : Float := 1.5;
   function Convert is new Ada.Unchecked_Conversion (Float, Integer);
   use Ada.Integer_Text_IO, Ada.Text_IO;
begin
   Put_Line ("Num =" & Num'Image);
   Put ("Hexadecimal representation = ");
   Put (Item => Convert (Num), Base => 16);
end Main;

If the sizes don't match, a good compiler will issue a warning:

main.adb:7:04: warning: types for unchecked conversion have different sizes [-gnatwz]

Note: for a professional use, don't use Float or Integer directly, define specific types.

Sign up to request clarification or add additional context in comments.

1 Comment

While Ada.Unchecked_Conversion is a good tool for this problem it still has the same basic problems as the answer provided by @Jim Rogers. That problem is the need for both types to have the same size and the same memory alignment. Both solutions are fully supported by the Ada Reference Manual.
1

This kind of conversion is contrary to Ada type safety but can be done using the following pattern.

with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Text_IO; use Ada.Text_IO;

procedure Main is
   Num : float := 1.5;
   Int : Integer;
   for Int'Address use Num'Address;
begin
   Put_Line("Num size is" & Integer'Image(Num'Size));
   Put_Line("Num =" & Num'Image);
   Put("Int = ");
   Put(Item => Int, Base => 16);
end Main;

The output of the program is:
Num size is 32

Num = 1.50000E+00

Int = 16#3FC00000#

Edit:

A somewhat more general solution not relying on Integer and Float having the same size is:

with Ada.Text_IO; use Ada.Text_IO;

procedure Main is
   Num : Long_Float := 1.5;
   type mod_num is mod 2**Float'Size;
   package mod_io is new Modular_IO (mod_num);
   use mod_io;
   Int : mod_num;
   for Int'Address use Num'Address;
begin
   Put_Line ("Num size is" & Integer'Image (Num'Size));
   Put_Line ("Num =" & Num'Image);
   Put ("Int = ");
   Put (Item => Int, Base => 16);
end Main;

Comments

1

Note that you cannot do that because IEEE 754 does not specify endianness. Depending on the machine endianness the bit pattern of IEEE 754 single precision float may vary.

As for converting IEEE 754 single precision float on the given machine to modular integer you can use

  • Unchecked_Conversion

  • Memory mapping (for X'Address use Y)

  • Unchecked union

First two have already been shown. Note that presented memory mapping is incorrect. When declaring a mapped object you need to add pragma Import (Ada, Int) to ensure absence initialization.

Here I show the third one:

   package IO is new Ada.Text_IO.Modular_IO (Unsigned_32);
   type Mode is (As_Float, As_Integer);
   type Mixed (Kind_Of : Mode := As_Float) is record
      case Kind_Of is
         when As_Float =>
            F : Interfaces.IEEE_Float_32; -- Machine-dependent
         when As_Integer =>
            I : Interfaces.Unsigned_32; 
      end case;
   end record;
   pragma Unchecked_Union (Mixed);
   Z : Mixed := (As_Float, 1.5); -- This is how you set float into the union
...
   IO.Put (Z.I, Base => 16); -- This is how you print it as an unsigned

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.