Hosted by
|
with Ada.Text_IO; use Ada.Text_IO;
with Messages; use Messages;
package body Digits_Strings is
function To_Number
(Value : in String)
return Number
is
Index : Positive := Value'First;
Result : Number := 0.0;
Negative : Boolean;
Dot_Found : Boolean := False;
Factor : Number := 1.0;
I : Integer;
begin
if Value'Length = 0 then return 0.0; end if;
Negative := Value(Index) = '-';
if Negative then Index := Index + 1; end if;
loop
exit when Index > Value'Last;
if Value(Index) = '.' then
Dot_Found := True;
Index := Index + 1;
end if;
exit when not (Value(Index) in '0' .. '9');
I := Character'Pos(Value(Index)) - Character'Pos('0');
if not Dot_Found then
Result := Result * 10.0 + Number(I);
else
Factor := Factor / 10.0;
Result := Result + Factor * Number(I);
end if;
Index := Index + 1;
end loop;
if Negative then Result := -Result; end if;
return Result;
end To_Number;
function To_String_Internal
(Value : in Number;
Done : in Number;
Divisor : in Number;
Tolerance : in Number)
return String
is
Rest : Number;
I : Integer;
C : Character;
Done2 : Number;
begin
Rest := Value - Done;
pragma Assert(Rest >= 0.0);
pragma Assert(Rest / Divisor < 10.0);
if Divisor <= Tolerance
then I := Integer(Rest / Divisor); -- Rounding the last digit.
else I := Integer(Number'Floor(Rest / Divisor));
end if;
C := Character'Val(Character'Pos('0') + I);
Done2 := Done + Number(I) * Divisor;
if Value - Done2 < Tolerance and Divisor < 5.0 then
return C & "";
elsif Divisor in 0.05 .. 0.5 then
return "." & C &
To_String_Internal(Value, Done2, Divisor / 10.0, Tolerance);
else
return C &
To_String_Internal(Value, Done2, Divisor / 10.0, Tolerance);
end if;
end To_String_Internal;
function Round_Up
(This : in String)
return String
is
Result : String := This;
Carry : Boolean := False;
begin
for Index in reverse Result'Range loop
if Result(Index) /= '.' then
if Carry then
Result(Index) := Character'Val(Character'Pos(Result(Index)) + 1);
end if;
Carry := Result(Index) = ':';
if Carry then
Result(Index) := '0';
end if;
end if;
end loop;
if Carry
then return '1' & Result;
else return Result;
end if;
end Round_Up;
function To_String
(Value : in Number;
Tolerance : in Number)
return String
is
Divisor : Number := 1.0;
Old_Divisor : Number;
begin
if Value <= -Tolerance then
return "-" & To_String(-Value, Tolerance);
elsif Value < Tolerance then
return "0";
else
while Divisor <= Value loop
Old_Divisor := Divisor;
Divisor := Divisor * 10.0;
if Old_Divisor = Divisor then
return "inf";
end if;
end loop;
declare
Result : String := To_String_Internal(Value, 0.0, Divisor / 10.0, Tolerance);
begin
return Round_Up(Result);
end;
end if;
end To_String;
function To_String
(Value : in Number)
return String is
begin
return To_String(Value, Default_Tolerance);
end To_String;
end Digits_Strings;
|