Safe addition

From Rosetta Code
Revision as of 08:48, 12 August 2009 by rosettacode>Dmitry-kazakov (New task + a solution)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Task
Safe addition
You are encouraged to solve this task according to the task description, using any language you may know.

Implementation of interval arithmetic and more generally fuzzy number arithmetic require operations that yield safe upper and lower bounds of the exact result. For example, for an addition, it is the operations *↑ and *↓ defined as: a +↓ ba + ba +↑ b. Additionally it is desired that the width of the interval (a +↑ b) - (a +↓ b) would be about the machine epsilon after removing the exponent part.

Differently to the standard floating-point arithmetic, safe interval arithmetic is accurate (but still imprecise). I.e. the result of each defined operation contains (though does not identify) the exact mathematical outcome.

Usually a FPU's have machine +,-,*,/ operations accurate within the machine precision. To illustrate it, let us consider a machine with decimal floating-point arithmetic that has the precision is 3 decimal points. If the result of the machine addition is 1.23, then the exact mathematical result is within the interval ]1.22, 1.24[. When the machine rounds towards zero, then the exact result is within [1.23,1.24[. This is the basis for an implementation of safe addition.

Task

Show how +↓ and +↑ can be implemented in your language using the standard floating-point type. Define an interval type based on the standard floating-point one, and implement an interval-valued addition of two floating-point numbers considering them exact, in short an operation that yields the interval [a +↓ b, a +↑ b].

Ada

An interval type based on Float: <lang Ada> type Interval is record

  Lower : Float;
  Upper : Float;

end record; </lang> Implementation of safe addition: <lang Ada> function "+" (A, B : Float) return Interval is

  Result : constant Float := A + B;

begin

  if Result < 0.0 then
     if Float'Machine_Rounds then
        return (Float'Adjacent (Result, Float'First), Float'Adjacent (Result, 0.0));
     else
        return (Float'Adjacent (Result, Float'First), Result);
     end if;         
  elsif Result > 0.0 then   
     if Float'Machine_Rounds then
        return (Float'Adjacent (Result, 0.0), Float'Adjacent (Result, Float'Last));
     else
        return (Result, Float'Adjacent (Result, Float'Last));
     end if;         
  else
     return (Result, Result);
  end if;

end "+"; </lang> Test program: <lang Ada> with Ada.Text_IO; use Ada.Text_IO; procedure Test_Interval_Addition is

  -- Definitions from above
  procedure Put (I : Interval) is
  begin
     Put (Long_Float'Image (Long_Float (I.Lower)) & "," & Long_Float'Image (Long_Float (I.Upper)));
  end Put;

begin

  Put (1.14 + 2000.0);

end Test_Interval_Addition; </lang> Sample output:

 2.00113989257813E+03, 2.00114013671875E+03