From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-2.5 required=5.0 tests=BAYES_00,MAILING_LIST_MULTI, STOX_REPLY_TYPE autolearn=unavailable autolearn_force=no version=3.4.4 X-Google-Thread: 103376,91965a012526b259 X-Google-Attributes: gid103376,public X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!news1.google.com!proxad.net!freenix!enst.fr!melchior!cuivre.fr.eu.org!melchior.frmug.org!not-for-mail From: "David C. Hoos, Sr." Newsgroups: comp.lang.ada Subject: Re: Float to String Date: Thu, 11 Nov 2004 09:53:55 -0600 Organization: Cuivre, Argent, Or Message-ID: References: <24Bkd.74362$HA.12207@attbi_s01> NNTP-Posting-Host: lovelace.ada-france.org Mime-Version: 1.0 Content-Type: text/plain; format=flowed; charset="iso-8859-1"; reply-type=original Content-Transfer-Encoding: 7bit X-Trace: melchior.cuivre.fr.eu.org 1100188503 82107 212.85.156.195 (11 Nov 2004 15:55:03 GMT) X-Complaints-To: usenet@melchior.cuivre.fr.eu.org NNTP-Posting-Date: Thu, 11 Nov 2004 15:55:03 +0000 (UTC) Cc: comp.lang.ada@ada-france.org To: "Pascal Obry" Return-Path: X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 6.00.2900.2180 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2180 X-Virus-Scanned: by amavisd-new-20030616-p10 (Debian) at ada-france.org X-BeenThere: comp.lang.ada@ada-france.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Gateway to the comp.lang.ada Usenet newsgroup" List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Xref: g2news1.google.com comp.lang.ada:6146 Date: 2004-11-11T09:53:55-06:00 Here is a solution that preserves every bit except the last bit in the floating point hardware. The string representation is that of the mantissa expressed as a decimal integer (with appropriate sign) followed by the power of the machine radix (2 on a Windows box) by which the integer must be multiplied to obtain the correct results. For example, the representation of the value -0.1 (a non- terminating number in binary is "-14757395258967641294-67". The representation of the value 0.5 (which can be exactly represented in binary is "9223372036854775808-64" (remember the mantissa representation is the decimal equivalent of a binary 1 followed by 64 zeroes). The solution is a generic package containing two functions (To_String and To_Value). The generic parameter for instantiation is the floating point type. For IEEE 32- and 64- bit types, the representation is exact in all of the cases I've tested. In the case of 80-bit IEEE, there are occasional differences of one LSB. So, here it is, along with a test program. the test program could be improved by generating a sequence of random numbers, and keeping track of the worst-case relative difference. File: precise_real_strings.ads ----------------------------------------------- generic type Real is digits <>; package Precise_Real_Strings is function To_String (Value : Real) return String; function To_Real (Representation : String) return Real; Format_Error : exception; end Precise_Real_Strings; ----------------------------------------------- File: precise_real_strings.adb ----------------------------------------------- with Ada.Exceptions; with Ada.Strings.Fixed; with Ada.Strings.Maps; with Interfaces; package body Precise_Real_Strings is procedure Reset; pragma Import (C, Reset, "__gnat_init_float"); -- We import the floating-point processor reset routine so that we can -- be sure the floating-point processor is properly set for conversion -- calls (see description of Reset in GNAT.Float_Control (g-flocon.ads). -- This is notably need on Windows, where calls to the operating system -- randomly reset the processor into 64-bit mode. ------------- -- To_Real -- ------------- function To_Real (Representation : String) return Real is Separator : Natural; Separators : constant String := " +-"; Sign_pos : Natural; Exponent : Integer; Mantissa : Interfaces.Unsigned_64; Is_Negative : Boolean; procedure Raise_With_Message is begin Ada.Exceptions.Raise_Exception (Format_Error'Identity, "Invalid representation: """ & Representation & """."); end; begin Reset; Separator := Ada.Strings.Fixed.Index (Representation (Representation'First + 1 .. Representation'Last), Ada.Strings.Maps.To_Set (separators)); if Separator = 0 then Raise_With_Message; end if; begin Exponent := Integer'Value (Representation (Separator .. Representation'Last)); exception when others => Raise_With_Message; end; Sign_pos := Ada.Strings.Fixed.Index (Representation (Representation'First .. Separator - 1), Ada.Strings.Maps.To_Set ('-')); Is_Negative := Sign_Pos /= 0; Mantissa := Interfaces.Unsigned_64'Value (Representation (Sign_Pos + 1 .. Separator - 1)); declare Result : Real := Real'Scaling (Real (Mantissa), Exponent); begin if Sign_Pos = 0 then return Result; else return - Result; end if; end; end To_Real; --------------- -- To_String -- --------------- function To_String (Value : Real) return String is Exponent : Integer; Mantissa : Interfaces.Unsigned_64; Sign : Character; begin Reset; if Value < 0.0 then Sign := '-'; else Sign := ' '; end if; Exponent := Real'Exponent (Value) -Real'Machine_Mantissa; Mantissa := Interfaces.Unsigned_64 (Real'Scaling (abs (Value), - Exponent)); declare Mantissa_String : String := Interfaces.Unsigned_64'Image (Mantissa); begin Mantissa_String (1) := Sign; return Mantissa_String & Integer'Image (Exponent); end; end To_String; end Precise_Real_Strings; ----------------------------------------------- File: test_precise_real_strings.adb ----------------------------------------------- with Ada.Text_IO; with Precise_Real_Strings; procedure Test_Precise_Real_Strings is package Llf is new Precise_Real_Strings (Long_Long_Float); package Lf is new Precise_Real_Strings (Long_Float); package F is new Precise_Real_Strings (Float); begin declare Representation : String := Llf.To_String (-0.1); begin Ada.Text_IO.Put_Line (Representation); Ada.Text_IO.Put_Line (Long_Long_Float'Image (Llf.To_Real (Representation))); Representation (1) := '+'; Ada.Text_IO.Put_Line (Long_Long_Float'Image (Llf.To_Real (Representation))); Representation (1) := ' '; Ada.Text_IO.Put_Line (Long_Long_Float'Image (Llf.To_Real (Representation))); Ada.Text_IO.Put_Line ("Relative difference:" & Long_Long_Float'Image ((Llf.To_Real (Representation) - 0.1)/ 0.1)); Ada.Text_IO.Put_Line ("Precise match? " & Boolean'Image (Llf.To_Real (Representation) = 0.1)); end; Ada.Text_IO.New_Line; declare Representation : String := Lf.To_String (-0.1); begin Ada.Text_IO.Put_Line (Representation); Ada.Text_IO.Put_Line (Long_Float'Image (Lf.To_Real (Representation))); Representation (1) := '+'; Ada.Text_IO.Put_Line (Long_Float'Image (Lf.To_Real (Representation))); Representation (1) := ' '; Ada.Text_IO.Put_Line (Long_Float'Image (Lf.To_Real (Representation))); Ada.Text_IO.Put_Line ("Relative difference:" & Long_Float'Image ((Lf.To_Real (Representation) - 0.1)/ 0.1)); Ada.Text_IO.Put_Line ("Precise match? " & Boolean'Image (Lf.To_Real (Representation) = 0.1)); end; Ada.Text_IO.New_Line; declare Representation : String := F.To_String (-0.1); begin Ada.Text_IO.Put_Line (Representation); Ada.Text_IO.Put_Line (Float'Image (F.To_Real (Representation))); Representation (1) := '+'; Ada.Text_IO.Put_Line (Float'Image (F.To_Real (Representation))); Representation (1) := ' '; Ada.Text_IO.Put_Line (Float'Image (F.To_Real (Representation))); Ada.Text_IO.Put_Line ("Relative difference:" & Float'Image ((F.To_Real (Representation) - 0.1)/ 0.1)); Ada.Text_IO.Put_Line ("Precise match? " & Boolean'Image (F.To_Real (Representation) = 0.1)); end; Ada.Text_IO.New_Line; end; ----------------------------------------------- Here are the results of ruinning the test program: -14757395258967641294-67 -1.00000000000000000E-01 1.00000000000000000E-01 1.00000000000000000E-01 Relative difference: 6.77626357803440271E-20 Precise match? FALSE -7205759403792794-56 -1.00000000000000E-01 1.00000000000000E-01 1.00000000000000E-01 Relative difference: 0.00000000000000E+00 Precise match? TRUE -13421773-27 -1.00000E-01 1.00000E-01 1.00000E-01 Relative difference: 0.00000E+00 Precise match? TRUE ----- Original Message ----- From: "Pascal Obry" Newsgroups: comp.lang.ada To: Sent: November 11, 2004 6:32 AM Subject: Re: Float to String > > tmoran@acm.org writes: > >> The cosine here is presumably a large integer divided by the square root >> of the product of two large integers. How about just writing the three >> integers, so the external representation is completely accurate. Then let >> the reader calculate the square root and division, thus generating as >> accurate a float as it possibly can, given its hardware. > > Hum, I don't think this is an option for me with the current design. > > Pascal. > > -- > > --|------------------------------------------------------ > --| Pascal Obry Team-Ada Member > --| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE > --|------------------------------------------------------ > --| http://www.obry.org > --| "The best way to travel is by means of imagination" > --| > --| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595 > _______________________________________________ > comp.lang.ada mailing list > comp.lang.ada@ada-france.org > http://www.ada-france.org/mailman/listinfo/comp.lang.ada > >