[comp.lang.ada] Truncation of FLOATs

ssj@castle.ed.ac.uk (S Johal) (01/11/90)

Hello ADA experts,

One of my colleagues has a problem which I hope somebody has an easy solution
to. Basically he is after the whole number part of a floating point number. We
found no way in ADA to directly implement it, so we tried something like:

    ROUNDED := INTEGER(FLOATING_NUMBER);
    if FLOATING_NUMBER - ROUNDED >= 0.0 then
      TRUNCATED_PART := ROUNDED;
    else
      TRUNCATED_PART := ROUNDED - 1;
    end if;

examples:  FLOATING_NUMBER       ROUNDED      TRUNCATED_PART
           6.4                   6            6
           6.6                   7            6
the problem is:
           7.0                   7            6 ??? when it should be 7

We have checked what 7.0 - 7.0 gives, and its not 0.0, which is the problem I
suppose. My colleague knows about converting to a string and taking off the
integer bit, but this is inefficient.

Any ideas ?

*-------------------------------------------*----------------------------*
*  Subindrao Johal,                         *++++++++++++++++++++++++++++*
*  SARI Project,                            *  tel:   031 668 1550 x219  *
*  Department of Electrical Engineering,    *  fax:   031 662 4678       *
*  University of Edinburgh,                 *  email: ssj@sari.ed.ac.uk  *
*  The King's Buildings, Edinburgh EH9 3JL  *++++++++++++++++++++++++++++*
*------------------------------------------------------------------------*

billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu (William Thomas Wolfe, 2847 ) (01/11/90)

From ssj@castle.ed.ac.uk (S Johal):
> [Trying to get the integer part of a floating point number:]
>     if FLOATING_NUMBER - ROUNDED >= 0.0 then
>       TRUNCATED_PART := ROUNDED;
>     else
>       TRUNCATED_PART := ROUNDED - 1;
>     end if;

   First, I currently handle it as follows:

      generic
         type FLOAT_TYPE is digits <>;
         type INTEGER_TYPE is range <>;
      function TRUNCATE (THE_FLOAT : in FLOAT_TYPE) return INTEGER_TYPE;
  
         -- Results may vary for values which are FLOAT_TYPE'EPSILON 
         --   less than a whole number, depending on the compiler.  It 
         --   makes use of the compiler's integer-to-real conversion 
         --   function, the semantics of which, at the point halfway 
         --   between two whole numbers, is defined to be 
         --   compiler-dependent (Ada 83 LRM 4.6 (7)).


      function TRUNCATE (THE_FLOAT : in FLOAT_TYPE) return INTEGER_TYPE is

      begin   -- function TRUNCATE 
         return INTEGER_TYPE (THE_FLOAT - (0.5 - FLOAT_TYPE'EPSILON));
             -- works correctly @ boundary iff rounding is down...
         -- Another option is:
         --    return ( INTEGER_TYPE'(10.0 * THE_FLOAT) / 10 );
         -- which eliminates the rounding error by truncating it away,
         --   but there are numeric overflow problems with this approach.
      end TRUNCATE;

   Fortunately, there is a new secondary standard from NUMWG which will
   provide a better-defined alternative; the proposed standard package
   GENERIC_PRIMITIVE_FUNCTIONS will provide a TRUNCATE function:

      function TRUNCATE (X : FLOAT_TYPE) return FLOAT_TYPE;

         -- may raise PRIMITIVE_FUNCTIONS_EXCEPTIONS.REPRESENTATION_ERROR

   I'm told that there will be an article posted in the near future which
   gives a comprehensive description of ths proposed standard, as well as
   another similar proposed standard package, GENERIC_ELEMENTARY_FUNCTIONS,
   so stay tuned.
  

   Bill Wolfe, wtwolfe@hubcap.clemson.edu