comp.lang.ada
 help / color / mirror / Atom feed
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

  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