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
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.
1 Comment
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 32Num = 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
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