Matthew Woodcraft <[EMAIL PROTECTED]> wrote:
>  I have a question for you. Consider this function:
> 
>  def f(n):
>      """Return the largest natural power of 2 which does not exceed n."""
>      if n < 1:
>          raise ValueError
>      i = 1
>      while i <= n:
>          j = i
>          i *= 2
>      return j
> 
>  If I pass it an instance of MyNumericClass, it will return an int or a
>  long, not an instance of MyNumericClass.
> 
>  In your view, is this a weakness of the implementation? Should the
>  author of the function make an effort to have it return a value of the
>  same type that it was passed?

Possibly... It is relatively easy to do anyway and reasonably cheap so
why not?  In this case a number about the same size as the original
number (possibly very large) will be returned so the argument that it
should return the same type is reasonably strong.

>>> def f(n):
...     """Return the largest natural power of 2 which does not exceed n."""
...     if n < 1:
...         raise ValueError
...     i = n - n + 1
...     while i <= n:
...         j = i
...         i *= 2
...     return j
... 
>>> f(1023)
512
>>> from decimal import Decimal
>>> f(Decimal("1023"))
Decimal("512")
>>> 

There are other ways of writing that

  i = n - n + 1

eg

  i = n.__class__(1)

It it basically saying "make me a numeric type with this value" so
maybe the __class__ is the clearest.  It assumes that the constructor
can co-erce an int into the type, wheras the first assumes that the
type can add an int.

Here is my function to calculate arctan() from any type.  The only
subtle bit for a general numeric type is detecting when we've
calculated enough, without using any specific knowledge about which
numeric type.

def arctan(x):
    """
    Calculate arctan(x)
    
    arctan(x) = x - x**3/3 + x**5/5 - ... (-1 < x < 1)
    """
    total = x
    power = x
    divisor = 1
    old_delta = None
    while 1:
        power *= x
        power *= x
        power = -power
        divisor += 2
        old_total = total
        total += power / divisor
        delta = abs(total - old_total)
        if old_delta is not None and delta >= old_delta:
            break
        old_delta = delta
    return total

>>> arctan(0.5)
0.46364760900080587
>>> arctan(Decimal("0.5"))
Decimal("0.4636476090008061162142562314")

-- 
Nick Craig-Wood <[EMAIL PROTECTED]> -- http://www.craig-wood.com/nick
-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to