From: "Björn Lundin" <b.f.lundin@gmail.com>
Subject: Re: Fixed vs float and precision and conversions
Date: Wed, 8 Jul 2020 20:08:13 +0200 [thread overview]
Message-ID: <re522e$mat$1@dont-email.me> (raw)
In-Reply-To: <518ff68b-1017-4775-8248-c40048b4fe67o@googlegroups.com>
Den 2020-07-08 kl. 18:16, skrev Shark8:
> On Wednesday, July 8, 2020 at 2:15:43 AM UTC-6, björn lundin wrote:
>> Den 2020-07-07 kl. 23:58, skrev Shark8:
>>> On Tuesday, July 7, 2020 at 3:10:22 PM UTC-6, björn lundin wrote:
>>>>
> Ok, so one thing to keep in mind here is that type-wise you're dealing not with two types, but *three* -- the type on the other side, the values in the Global_Odds_Table; the IEEE754 transport, via JSON serialization and deserialization; and the type on your side, Fixed_Type.
hmm no. valuies in global_odds_table are fixed_type
Global_Odds_Table : array(Tics_Type'Range) of Fixed_Type := (
The type on the other side arrive in JSON as float. In deserialisation I
convert to Fixed_Type.
I don't quite follow you
>
> So then, the correct way to set up your end of things is to have a Fixed_Type which only has the values of Global_Odds_Table for your general-purpose/internal-usage, and have a conversion function for handling the IEEE754; here you are:
>
> Lowest_Odds : Constant := 1.01;
> Highest_Odds : Constant := 1_000.00;
> type Odds_Base is delta 0.001 digits 18 range Lowest_Odds..Highest_Odds;
> Subtype Odds is Odds_Base -- range Lowest_Odds..Hihgest_Odds
> with Predicate_Failure => raise Constraint_Error with
> Odds_Base'Image(Odds) & " is not a valid value.",
> Static_Predicate => Odds in
> -- Global_Odds_Table
> 1.01 | 1.02 | 1.03 | 1.04 | 1.05 |
> 2.00 | 2.02 | 2.04 | 2.06 | 2.08 | 2.10 |
> 3.00 | 3.05 | 3.10 | 3.15 | 3.20 | 3.25 |
> 4.00 | 4.10 | 4.20 | 4.30 | 4.40 | 4.50 |
> 5.00 | 5.10 | 5.20 | 5.30 | 5.40 | 5.50 |
> 10.00 | 10.50 | 11.00 | 11.50 | 12.00 | 12.50 |
> 20.00 | 21.00 | 22.00 | 23.00 | 24.00 | 25.00 |
> 50.00 | 55.00 | 60.00 | 65.00 | 70.00 | 75.00 |
> 100.00 | 110.00 | 120.00 | 130.00 | 140.00 | 150.00 |
> 960.00 | 970.00 | 980.00 | 990.00 |1000.00 ;
>
> Function Convert( Input : Interfaces.IEEE_Float_32 ) return Odds is
> use Interfaces;
> Begin
> Ada.Text_IO.Put_Line( "Input:" & Input'Image );
> Ada.Text_IO.Put_Line( "OB:" & Odds_Base'Round(Input)'Image );
> Return Odds'Round( Input );
> Exception
> When Constraint_Error =>
> -- Handle out-of-range errors.
> if Input < Lowest_Odds then
> return Lowest_Odds;
> elsif Input > Highest_Odds then
> return Highest_Odds;
> else
> declare
> -- Global_Odds_Table
> Table : Constant Array (Positive range <>) of IEEE_Float_32 :=
> ( 1.01, 1.02, 1.03, 1.04, 1.05,
> 2.00, 2.02, 2.04, 2.06, 2.08, 2.10,
> 3.00, 3.05, 3.10, 3.15, 3.20, 3.25,
> 4.00, 4.10, 4.20, 4.30, 4.40, 4.50,
> 5.00, 5.10, 5.20, 5.30, 5.40, 5.50,
> 10.00, 10.50, 11.00, 11.50, 12.00, 12.50,
> 20.00, 21.00, 22.00, 23.00, 24.00, 25.00,
> 50.00, 55.00, 60.00, 65.00, 70.00, 75.00,
> 100.00, 110.00, 120.00, 130.00, 140.00, 150.00,
> 960.00, 970.00, 980.00, 990.00,1000.00 );
> Closest_Index : Positive := 1;
> Closest_Value : IEEE_Float_32 := IEEE_Float_32'Last;
> begin
> For X in Table'Range loop
> if abs (Input - Table(X)) < Closest_Value then
> Closest_Value:= abs (Input - Table(X));
> Closest_Index:= X;
> end if;
> end loop;
>
> Return Odds'Round( Table(Closest_Index) );
> end;
> end if;
> End Convert;
>
> The bad thing here is that you have to repeat Global_Odds_Table, though this isn't so bad as the second is fully contained within the exception-handler; further, searching the table is done only when 'Round cannot be used directly. Also, this version does catch out of bounds errors and coerce them to the nearest bound. -- You might want to write a one-off program to generate the Predicate-form and array-value form of Global_Odds_Table, since there's 350 values.
>
hmm, nice. I'll implement this if not the thing I implemented and
deployed *10* minutes ago works.
it is based on the fact that I have a float-to-fixed_type converted
price in a fixed_type variable.
It -as it turns out - can be
* too low for a specific value (as 5.099 vs 5.10)
* correct
* too high for a specific value
So I call below function with the converted value,
and then I look up returned index in the table/array
It also only goes to fix things only if incorrect/illegal value
---------
function Get_Tic_Index(Price : Fixed_Type) return Tics_Type is
begin
--optimistic approch - we have the coorect conversion
for I in Global_Odds_Table'Range loop
if Global_Odds_Table(I) = Price then
return I;
end if;
end loop;
-- ok - did not find any -> bad float then
-- it has to be a valid value within min an max
declare
P : Fixed_Type;
D : Fixed_Type := 0.001 ;
Min : Fixed_Type;
Max : Fixed_Type;
begin
-- Find Index in odds table which is just below given odds
for I in Global_Odds_Table'Range loop
if Global_Odds_Table(I) < Price then
Min := Global_Odds_Table(I);
else
exit; -- must have found it
end if;
end loop;
-- Find Index in odds table which is just above given odds
for I in Global_Odds_Table'Range loop
if Global_Odds_Table(I) > Price then
Max := Global_Odds_Table(I);
exit;
end if;
end loop;
-- now step carefully util we get a hit or we have to give up
Log("Get_Tic_Index", "try fixing bad float price " & Price'Img);
P := Min + D;
loop
for I in Global_Odds_Table'Range loop
if Global_Odds_Table(I) = P then
Log("Get_Tic_Index", "fixed bad float - min/max " &
Min'Img & " / " & Max'Img);
return I;
end if;
end loop;
exit when P > Max; --give up, and propagate exception
Log("Get_Tic_Index", "fixing bad float p/min/max " & P'Img &
Min'Img & " / " & Max'Img);
P := P + D;
end loop;
Log("Get_Tic_Index", "did not fix bad float min/max " & Min'Img
& " / " & Max'Img);
end;
raise Bad_Odds with Price'Img;
end Get_Tic_Index;
---------
Thanks for the time and effort
--
Björn
next prev parent reply other threads:[~2020-07-08 18:08 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-07-07 21:10 Fixed vs float and precision and conversions Björn Lundin
2020-07-07 21:30 ` Niklas Holsti
2020-07-08 8:17 ` Björn Lundin
2020-07-07 21:58 ` Shark8
2020-07-08 8:15 ` Björn Lundin
2020-07-08 16:16 ` Shark8
2020-07-08 18:08 ` Björn Lundin [this message]
2020-07-08 18:10 ` Björn Lundin
2020-07-08 18:21 ` Niklas Holsti
2020-07-08 19:39 ` Björn Lundin
2020-07-08 20:34 ` Niklas Holsti
2020-07-08 21:24 ` Björn Lundin
2020-07-09 7:11 ` Niklas Holsti
2020-07-08 18:36 ` Dmitry A. Kazakov
2020-07-08 19:41 ` Björn Lundin
2020-07-09 6:20 ` Dmitry A. Kazakov
2020-07-09 7:23 ` Björn Lundin
2020-07-09 7:49 ` Dmitry A. Kazakov
2020-07-08 21:16 ` Shark8
2020-07-08 21:47 ` Björn Lundin
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox