Previous Page Next Page Contents

numeric::rationalize -- approximate a floating point number by a rational number

Introduction

numeric::rationalize(object, ..) replaces all floating point numbers in object by rational numbers.

Call(s)

numeric::rationalize(object <, mode> <, digits>)

Parameters

object - an arbitrary MuPAD object

Options

mode - either Exact, or Minimize, or Restore. This controls the strategy for approximating floating point numbers by rational numbers.
digits - a positive integer (the number of decimal digits) not bigger than the environment variable DIGITS. It determines the precision of the rational approximation.

Returns

If the argument is an object of some kernel domain, then it is returned with all floating point operands replaced by rational numbers. An object of some library domain is returned unchanged.

Overloadable:

object

Side Effects

The function is sensitive to the environment variable DIGITS.

Details

Option: digits

Option: Exact

Option: Minimize

Option: Restore

Example 1

numeric::rationalize is applied to each operand of a composite object:

>> numeric::rationalize(0.2*a+b^(0.7*I))
                                a    7/10 I
                                - + b
                                5
>> numeric::rationalize([{poly(0.2*x, [x]), sin(7.2*PI) + 1.0*I},
                         exp(3 + ln(2.0*x))])
      -- {                      / 36 PI \     }                   --
      |  { poly(1/5 x, [x]), sin| ----- | + I }, exp(ln(2 x) + 3)  |
      -- {                      \   5   /     }                   --

Example 2

We demonstrate the default strategy Exact:

>> numeric::rationalize(12.3 + 0.5*I),
   numeric::rationalize(0.33333), 
   numeric::rationalize(1/3.0)
          123/10 + 1/2 I, 33333/100000, 33333333333/100000000000
>> numeric::rationalize(10^12/13.0),
   numeric::rationalize(10^(-12)/13.0)
            76923076923, 76923076923/1000000000000000000000000

We reduce the precision of the approximation to 5 digits:

>> numeric::rationalize(10^12/13.0, 5),
   numeric::rationalize(10^(-12)/13.0, 5)
                 76923100000, 769231/10000000000000000000

Example 3

We demonstrate the strategy Minimize for minimizing the complexity of the resulting rational number:

>> numeric::rationalize(1/13.0, 5),
   numeric::rationalize(1/13.0, Minimize, 5),
   numeric::rationalize(0.333331, 5),
   numeric::rationalize(0.333331, Minimize, 5),
   numeric::rationalize(14.285, 5),
   numeric::rationalize(14.2857, Minimize, 5),
   numeric::rationalize(1234.1/56789.2),
   numeric::rationalize(1234.1/56789.2, Minimize)
      769231/10000000, 1/13, 333331/1000000, 1/3, 2857/200, 100/7,
      
         21731244673/1000000000000, 12341/567892

We compute rational approximations of PI with various precisions:

>> numeric::rationalize(float(PI), Minimize, i) $ i = 1..10
      3, 22/7, 22/7, 355/113, 355/113, 355/113, 355/113,
      
         102573/32650, 104348/33215, 208341/66317

Example 4

We demonstrate the strategy Restore for restoring rational numbers after elementary float operations. In many cases also the Minimize strategy restores:

>> numeric::rationalize(1/7.3, Exact),
   numeric::rationalize(1/7.3, Minimize),
   numeric::rationalize(1/7.3, Restore)
                  13698630137/100000000000, 10/73, 10/73

However, using Restore improves the chances of recovering from round-off effects:

>> numeric::rationalize(10^12/13.0, Minimize),
   numeric::rationalize(10^12/13.0, Restore)
                       76923076923, 1000000000000/13
>> numeric::rationalize(123.456/12.34567, Minimize),
   numeric::rationalize(123.456/12.34567, Restore)
                      529097/52910, 12345600/1234567

In some cases Restore manages to recover from round-off error propagation in composite arithmetical operations:

>> x := 125/12.34567: y := 123/12.34567: z := (x^2 - y^2)/(x + y)
                               0.1620001183
>> numeric::rationalize(z, Minimize),
   numeric::rationalize(z, Restore)
                       35612/219827, 200000/1234567

The result with Restore corresponds to exact arithmetic:

>> rx := numeric::rationalize(x, Restore):
>> ry := numeric::rationalize(y, Restore):
>> (rx^2 - ry^2)/(rx + ry)
                              200000/1234567

Note that an approximation with Restore may have a reduced precision of only digits/2:

>> x := 1.0 + 1/10^6:
>> numeric::rationalize(x, Exact),
   numeric::rationalize(x, Restore)
                            1000001/1000000, 1
>> delete x, y, z, rx, ry:

Example 5

The floats inside objects of library domains are not rationalized directly. However, for most domains the corresponding map method can forward numeric::rationalize to the operands:

>> Dom::Multiset(0.2, 0.2, 1/5, 0.3)
                      {[0.3, 1], [0.2, 2], [1/5, 1]}
>> numeric::rationalize(%), map(%, numeric::rationalize, Restore)
           {[0.3, 1], [0.2, 2], [1/5, 1]}, {[1/5, 3], [3/10, 1]}

Background

Changes




Do you have questions or comments?


Copyright © SciFace Software GmbH & Co. KG 2000