Merged revisions 60481,60485,60489-60492,60494-60496,60498-60499,60501-60503,60505-60506,60508-60509,60523-60524,60532,60543,60545,60547-60548,60552,60554,60556-60559,60561-60562,60569,60571-60572,60574,60576-60583,60585-60586,60589,60591,60594-60595,60597-60598,60600-60601,60606-60612,60615,60617,60619-60621,60623-60625,60627-60629,60631,60633,60635,60647,60650,60652,60654,60656,60658-60659,60664-60666,60668-60670,60672,60676,60678,60680-60683,60685-60686,60688,60690,60692-60694,60697-60700,60705-60706,60708,60711,60714,60720,60724-60730,60732,60736,60742,60744,60746,60748,60750-60766,60769-60786 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r60752 | mark.dickinson | 2008-02-12 22:31:59 +0100 (Tue, 12 Feb 2008) | 5 lines

  Implementation of Fraction.limit_denominator.

  Remove Fraction.to_continued_fraction and
  Fraction.from_continued_fraction
........
  r60754 | mark.dickinson | 2008-02-12 22:40:53 +0100 (Tue, 12 Feb 2008) | 3 lines

  Revert change in r60712:  turn alternate constructors back into
  classmethods instead of staticmethods.
........
  r60755 | mark.dickinson | 2008-02-12 22:46:54 +0100 (Tue, 12 Feb 2008) | 4 lines

  Replace R=fractions.Fraction with F=fractions.Fraction in
  test_fractions.py.  This should have been part of the name
  change from Rational to Fraction.
........
  r60758 | georg.brandl | 2008-02-13 08:20:22 +0100 (Wed, 13 Feb 2008) | 3 lines

  #2063: correct order of utime and stime in os.times()
  result on Windows.
........
  r60762 | jeffrey.yasskin | 2008-02-13 18:58:04 +0100 (Wed, 13 Feb 2008) | 7 lines

  Working on issue #1762: Brought
    ./python.exe -m timeit -s 'from fractions import Fraction; f = Fraction(3, 2)' 'isinstance(3, Fraction); isinstance(f, Fraction)'
  from 12.3 usec/loop to 3.44 usec/loop and
    ./python.exe -m timeit -s 'from fractions import Fraction' 'Fraction(3, 2)'
  from 48.8 usec to 23.6 usec by avoiding genexps and sets in __instancecheck__
  and inlining the common case from __subclasscheck__.
........
  r60765 | brett.cannon | 2008-02-13 20:15:44 +0100 (Wed, 13 Feb 2008) | 5 lines

  Fix --enable-universalsdk and its comment line so that zsh's flag completion
  works.

  Thanks to Jeroen Ruigrok van der Werven for the fix.
........
  r60771 | kurt.kaiser | 2008-02-14 01:08:55 +0100 (Thu, 14 Feb 2008) | 2 lines

  Bring NEWS.txt up to date from check-in msgs.
........
  r60772 | raymond.hettinger | 2008-02-14 02:08:02 +0100 (Thu, 14 Feb 2008) | 3 lines

  Update notes on Decimal.
........
  r60773 | raymond.hettinger | 2008-02-14 03:41:22 +0100 (Thu, 14 Feb 2008) | 1 line

  Fix decimal repr which should have used single quotes like other reprs.
........
  r60785 | jeffrey.yasskin | 2008-02-14 07:12:24 +0100 (Thu, 14 Feb 2008) | 11 lines

  Performance optimizations on Fraction's constructor.

    ./python.exe -m timeit -s 'from fractions import Fraction' 'Fraction(3)`
  31.7 usec/loop -> 9.2 usec/loop

    ./python.exe -m timeit -s 'from fractions import Fraction' 'Fraction(3, 2)'`
  27.7 usec/loop -> 9.32 usec/loop

    ./python.exe -m timeit -s 'from fractions import Fraction; f = Fraction(3, 2)' 'Fraction(f)'
  31.9 usec/loop -> 14.3 usec/loop
........
  r60786 | jeffrey.yasskin | 2008-02-14 08:49:25 +0100 (Thu, 14 Feb 2008) | 5 lines

  Change simple instances (in Fraction) of self.numerator and self.denominator to
  self._numerator and self._denominator. This speeds abs() up from 12.2us to
  10.8us and trunc() from 2.07us to 1.11us. This doesn't change _add and friends
  because they're more complicated.
........
This commit is contained in:
Christian Heimes 2008-02-14 08:27:37 +00:00
parent 9d0d616c3b
commit 68f5fbe944
14 changed files with 675 additions and 627 deletions

View File

@ -46,10 +46,10 @@ arithmetic. It offers several advantages over the :class:`float` datatype:
>>> getcontext().prec = 6 >>> getcontext().prec = 6
>>> Decimal(1) / Decimal(7) >>> Decimal(1) / Decimal(7)
Decimal("0.142857") Decimal('0.142857')
>>> getcontext().prec = 28 >>> getcontext().prec = 28
>>> Decimal(1) / Decimal(7) >>> Decimal(1) / Decimal(7)
Decimal("0.1428571428571428571428571429") Decimal('0.1428571428571428571428571429')
* Both binary and decimal floating point are implemented in terms of published * Both binary and decimal floating point are implemented in terms of published
standards. While the built-in float type exposes only a modest portion of its standards. While the built-in float type exposes only a modest portion of its
@ -128,19 +128,19 @@ representation error). Decimal numbers include special values such as
:const:`Infinity`, and :const:`-0`. :: :const:`Infinity`, and :const:`-0`. ::
>>> Decimal(10) >>> Decimal(10)
Decimal("10") Decimal('10')
>>> Decimal("3.14") >>> Decimal('3.14')
Decimal("3.14") Decimal('3.14')
>>> Decimal((0, (3, 1, 4), -2)) >>> Decimal((0, (3, 1, 4), -2))
Decimal("3.14") Decimal('3.14')
>>> Decimal(str(2.0 ** 0.5)) >>> Decimal(str(2.0 ** 0.5))
Decimal("1.41421356237") Decimal('1.41421356237')
>>> Decimal(2) ** Decimal("0.5") >>> Decimal(2) ** Decimal('0.5')
Decimal("1.414213562373095048801688724") Decimal('1.414213562373095048801688724')
>>> Decimal("NaN") >>> Decimal('NaN')
Decimal("NaN") Decimal('NaN')
>>> Decimal("-Infinity") >>> Decimal('-Infinity')
Decimal("-Infinity") Decimal('-Infinity')
The significance of a new Decimal is determined solely by the number of digits The significance of a new Decimal is determined solely by the number of digits
input. Context precision and rounding only come into play during arithmetic input. Context precision and rounding only come into play during arithmetic
@ -148,28 +148,28 @@ operations. ::
>>> getcontext().prec = 6 >>> getcontext().prec = 6
>>> Decimal('3.0') >>> Decimal('3.0')
Decimal("3.0") Decimal('3.0')
>>> Decimal('3.1415926535') >>> Decimal('3.1415926535')
Decimal("3.1415926535") Decimal('3.1415926535')
>>> Decimal('3.1415926535') + Decimal('2.7182818285') >>> Decimal('3.1415926535') + Decimal('2.7182818285')
Decimal("5.85987") Decimal('5.85987')
>>> getcontext().rounding = ROUND_UP >>> getcontext().rounding = ROUND_UP
>>> Decimal('3.1415926535') + Decimal('2.7182818285') >>> Decimal('3.1415926535') + Decimal('2.7182818285')
Decimal("5.85988") Decimal('5.85988')
Decimals interact well with much of the rest of Python. Here is a small decimal Decimals interact well with much of the rest of Python. Here is a small decimal
floating point flying circus:: floating point flying circus::
>>> data = map(Decimal, '1.34 1.87 3.45 2.35 1.00 0.03 9.25'.split()) >>> data = map(Decimal, '1.34 1.87 3.45 2.35 1.00 0.03 9.25'.split())
>>> max(data) >>> max(data)
Decimal("9.25") Decimal('9.25')
>>> min(data) >>> min(data)
Decimal("0.03") Decimal('0.03')
>>> sorted(data) >>> sorted(data)
[Decimal("0.03"), Decimal("1.00"), Decimal("1.34"), Decimal("1.87"), [Decimal('0.03'), Decimal('1.00'), Decimal('1.34'), Decimal('1.87'),
Decimal("2.35"), Decimal("3.45"), Decimal("9.25")] Decimal('2.35'), Decimal('3.45'), Decimal('9.25')]
>>> sum(data) >>> sum(data)
Decimal("19.29") Decimal('19.29')
>>> a,b,c = data[:3] >>> a,b,c = data[:3]
>>> str(a) >>> str(a)
'1.34' '1.34'
@ -180,31 +180,31 @@ floating point flying circus::
>>> int(a) >>> int(a)
1 1
>>> a * 5 >>> a * 5
Decimal("6.70") Decimal('6.70')
>>> a * b >>> a * b
Decimal("2.5058") Decimal('2.5058')
>>> c % a >>> c % a
Decimal("0.77") Decimal('0.77')
And some mathematical functions are also available to Decimal:: And some mathematical functions are also available to Decimal::
>>> Decimal(2).sqrt() >>> Decimal(2).sqrt()
Decimal("1.414213562373095048801688724") Decimal('1.414213562373095048801688724')
>>> Decimal(1).exp() >>> Decimal(1).exp()
Decimal("2.718281828459045235360287471") Decimal('2.718281828459045235360287471')
>>> Decimal("10").ln() >>> Decimal('10').ln()
Decimal("2.302585092994045684017991455") Decimal('2.302585092994045684017991455')
>>> Decimal("10").log10() >>> Decimal('10').log10()
Decimal("1") Decimal('1')
The :meth:`quantize` method rounds a number to a fixed exponent. This method is The :meth:`quantize` method rounds a number to a fixed exponent. This method is
useful for monetary applications that often round results to a fixed number of useful for monetary applications that often round results to a fixed number of
places:: places::
>>> Decimal('7.325').quantize(Decimal('.01'), rounding=ROUND_DOWN) >>> Decimal('7.325').quantize(Decimal('.01'), rounding=ROUND_DOWN)
Decimal("7.32") Decimal('7.32')
>>> Decimal('7.325').quantize(Decimal('1.'), rounding=ROUND_UP) >>> Decimal('7.325').quantize(Decimal('1.'), rounding=ROUND_UP)
Decimal("8") Decimal('8')
As shown above, the :func:`getcontext` function accesses the current context and As shown above, the :func:`getcontext` function accesses the current context and
allows the settings to be changed. This approach meets the needs of most allows the settings to be changed. This approach meets the needs of most
@ -222,16 +222,16 @@ enabled::
>>> myothercontext = Context(prec=60, rounding=ROUND_HALF_DOWN) >>> myothercontext = Context(prec=60, rounding=ROUND_HALF_DOWN)
>>> setcontext(myothercontext) >>> setcontext(myothercontext)
>>> Decimal(1) / Decimal(7) >>> Decimal(1) / Decimal(7)
Decimal("0.142857142857142857142857142857142857142857142857142857142857") Decimal('0.142857142857142857142857142857142857142857142857142857142857')
>>> ExtendedContext >>> ExtendedContext
Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999,
capitals=1, flags=[], traps=[]) capitals=1, flags=[], traps=[])
>>> setcontext(ExtendedContext) >>> setcontext(ExtendedContext)
>>> Decimal(1) / Decimal(7) >>> Decimal(1) / Decimal(7)
Decimal("0.142857143") Decimal('0.142857143')
>>> Decimal(42) / Decimal(0) >>> Decimal(42) / Decimal(0)
Decimal("Infinity") Decimal('Infinity')
>>> setcontext(BasicContext) >>> setcontext(BasicContext)
>>> Decimal(42) / Decimal(0) >>> Decimal(42) / Decimal(0)
@ -248,7 +248,7 @@ using the :meth:`clear_flags` method. ::
>>> setcontext(ExtendedContext) >>> setcontext(ExtendedContext)
>>> getcontext().clear_flags() >>> getcontext().clear_flags()
>>> Decimal(355) / Decimal(113) >>> Decimal(355) / Decimal(113)
Decimal("3.14159292") Decimal('3.14159292')
>>> getcontext() >>> getcontext()
Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999,
capitals=1, flags=[Inexact, Rounded], traps=[]) capitals=1, flags=[Inexact, Rounded], traps=[])
@ -261,7 +261,7 @@ Individual traps are set using the dictionary in the :attr:`traps` field of a
context:: context::
>>> Decimal(1) / Decimal(0) >>> Decimal(1) / Decimal(0)
Decimal("Infinity") Decimal('Infinity')
>>> getcontext().traps[DivisionByZero] = 1 >>> getcontext().traps[DivisionByZero] = 1
>>> Decimal(1) / Decimal(0) >>> Decimal(1) / Decimal(0)
Traceback (most recent call last): Traceback (most recent call last):
@ -289,7 +289,7 @@ Decimal objects
Construct a new :class:`Decimal` object based from *value*. Construct a new :class:`Decimal` object based from *value*.
*value* can be an integer, string, tuple, or another :class:`Decimal` *value* can be an integer, string, tuple, or another :class:`Decimal`
object. If no *value* is given, returns ``Decimal("0")``. If *value* is a object. If no *value* is given, returns ``Decimal('0')``. If *value* is a
string, it should conform to the decimal numeric string syntax after leading string, it should conform to the decimal numeric string syntax after leading
and trailing whitespace characters are removed:: and trailing whitespace characters are removed::
@ -307,11 +307,11 @@ Decimal objects
If *value* is a :class:`tuple`, it should have three components, a sign If *value* is a :class:`tuple`, it should have three components, a sign
(:const:`0` for positive or :const:`1` for negative), a :class:`tuple` of (:const:`0` for positive or :const:`1` for negative), a :class:`tuple` of
digits, and an integer exponent. For example, ``Decimal((0, (1, 4, 1, 4), -3))`` digits, and an integer exponent. For example, ``Decimal((0, (1, 4, 1, 4), -3))``
returns ``Decimal("1.414")``. returns ``Decimal('1.414')``.
The *context* precision does not affect how many digits are stored. That is The *context* precision does not affect how many digits are stored. That is
determined exclusively by the number of digits in *value*. For example, determined exclusively by the number of digits in *value*. For example,
``Decimal("3.00000")`` records all five zeros even if the context precision is ``Decimal('3.00000')`` records all five zeros even if the context precision is
only three. only three.
The purpose of the *context* argument is determining what to do if *value* is a The purpose of the *context* argument is determining what to do if *value* is a
@ -338,7 +338,7 @@ also have a number of specialized methods:
.. method:: Decimal.adjusted() .. method:: Decimal.adjusted()
Return the adjusted exponent after shifting out the coefficient's rightmost Return the adjusted exponent after shifting out the coefficient's rightmost
digits until only the lead digit remains: ``Decimal("321e+5").adjusted()`` digits until only the lead digit remains: ``Decimal('321e+5').adjusted()``
returns seven. Used for determining the position of the most significant digit returns seven. Used for determining the position of the most significant digit
with respect to the decimal point. with respect to the decimal point.
@ -367,10 +367,10 @@ also have a number of specialized methods:
instance rather than an integer, and if either operand is a NaN instance rather than an integer, and if either operand is a NaN
then the result is a NaN:: then the result is a NaN::
a or b is a NaN ==> Decimal("NaN") a or b is a NaN ==> Decimal('NaN')
a < b ==> Decimal("-1") a < b ==> Decimal('-1')
a == b ==> Decimal("0") a == b ==> Decimal('0')
a > b ==> Decimal("1") a > b ==> Decimal('1')
.. method:: Decimal.compare_signal(other[, context]) .. method:: Decimal.compare_signal(other[, context])
@ -389,14 +389,14 @@ also have a number of specialized methods:
value but different representations compare unequal in this value but different representations compare unequal in this
ordering:: ordering::
>>> Decimal("12.0").compare_total(Decimal("12")) >>> Decimal('12.0').compare_total(Decimal('12'))
Decimal("-1") Decimal('-1')
Quiet and signaling NaNs are also included in the total ordering. Quiet and signaling NaNs are also included in the total ordering.
The result of this function is ``Decimal("0")`` if both operands The result of this function is ``Decimal('0')`` if both operands
have the same representation, ``Decimal("-1")`` if the first have the same representation, ``Decimal('-1')`` if the first
operand is lower in the total order than the second, and operand is lower in the total order than the second, and
``Decimal("1")`` if the first operand is higher in the total order ``Decimal('1')`` if the first operand is higher in the total order
than the second operand. See the specification for details of the than the second operand. See the specification for details of the
total order. total order.
@ -428,8 +428,8 @@ also have a number of specialized methods:
Return a copy of the first operand with the sign set to be the Return a copy of the first operand with the sign set to be the
same as the sign of the second operand. For example:: same as the sign of the second operand. For example::
>>> Decimal("2.3").copy_sign(Decimal("-1.5")) >>> Decimal('2.3').copy_sign(Decimal('-1.5'))
Decimal("-2.3") Decimal('-2.3')
This operation is unaffected by the context and is quiet: no flags This operation is unaffected by the context and is quiet: no flags
are changed and no rounding is performed. are changed and no rounding is performed.
@ -442,9 +442,9 @@ also have a number of specialized methods:
:const:`ROUND_HALF_EVEN` rounding mode. :const:`ROUND_HALF_EVEN` rounding mode.
>>> Decimal(1).exp() >>> Decimal(1).exp()
Decimal("2.718281828459045235360287471") Decimal('2.718281828459045235360287471')
>>> Decimal(321).exp() >>> Decimal(321).exp()
Decimal("2.561702493119680037517373933E+139") Decimal('2.561702493119680037517373933E+139')
.. method:: Decimal.fma(other, third[, context]) .. method:: Decimal.fma(other, third[, context])
@ -453,7 +453,7 @@ also have a number of specialized methods:
the intermediate product self*other. the intermediate product self*other.
>>> Decimal(2).fma(3, 5) >>> Decimal(2).fma(3, 5)
Decimal("11") Decimal('11')
.. method:: Decimal.is_canonical() .. method:: Decimal.is_canonical()
@ -537,9 +537,9 @@ also have a number of specialized methods:
For a nonzero number, return the adjusted exponent of its operand For a nonzero number, return the adjusted exponent of its operand
as a :class:`Decimal` instance. If the operand is a zero then as a :class:`Decimal` instance. If the operand is a zero then
``Decimal("-Infinity")`` is returned and the ``Decimal('-Infinity')`` is returned and the
:const:`DivisionByZero` flag is raised. If the operand is an :const:`DivisionByZero` flag is raised. If the operand is an
infinity then ``Decimal("Infinity")`` is returned. infinity then ``Decimal('Infinity')`` is returned.
.. method:: Decimal.logical_and(other[, context]) .. method:: Decimal.logical_and(other[, context])
@ -620,10 +620,10 @@ also have a number of specialized methods:
.. method:: Decimal.normalize([context]) .. method:: Decimal.normalize([context])
Normalize the number by stripping the rightmost trailing zeros and converting Normalize the number by stripping the rightmost trailing zeros and converting
any result equal to :const:`Decimal("0")` to :const:`Decimal("0e0")`. Used for any result equal to :const:`Decimal('0')` to :const:`Decimal('0e0')`. Used for
producing canonical values for members of an equivalence class. For example, producing canonical values for members of an equivalence class. For example,
``Decimal("32.100")`` and ``Decimal("0.321000e+2")`` both normalize to the ``Decimal('32.100')`` and ``Decimal('0.321000e+2')`` both normalize to the
equivalent value ``Decimal("32.1")``. equivalent value ``Decimal('32.1')``.
.. method:: Decimal.number_class([context]) .. method:: Decimal.number_class([context])
@ -648,8 +648,8 @@ also have a number of specialized methods:
Return a value equal to the first operand after rounding and Return a value equal to the first operand after rounding and
having the exponent of the second operand. having the exponent of the second operand.
>>> Decimal("1.41421356").quantize(Decimal("1.000")) >>> Decimal('1.41421356').quantize(Decimal('1.000'))
Decimal("1.414") Decimal('1.414')
Unlike other operations, if the length of the coefficient after the Unlike other operations, if the length of the coefficient after the
quantize operation would be greater than precision, then an quantize operation would be greater than precision, then an
@ -680,7 +680,7 @@ also have a number of specialized methods:
Compute the modulo as either a positive or negative value depending on which is Compute the modulo as either a positive or negative value depending on which is
closest to zero. For instance, ``Decimal(10).remainder_near(6)`` returns closest to zero. For instance, ``Decimal(10).remainder_near(6)`` returns
``Decimal("-2")`` which is closer to zero than ``Decimal("4")``. ``Decimal('-2')`` which is closer to zero than ``Decimal('4')``.
If both are equally close, the one chosen will have the same sign as *self*. If both are equally close, the one chosen will have the same sign as *self*.
@ -732,7 +732,7 @@ also have a number of specialized methods:
Engineering notation has an exponent which is a multiple of 3, so there are up Engineering notation has an exponent which is a multiple of 3, so there are up
to 3 digits left of the decimal place. For example, converts to 3 digits left of the decimal place. For example, converts
``Decimal('123E+1')`` to ``Decimal("1.23E+3")`` ``Decimal('123E+1')`` to ``Decimal('1.23E+3')``
.. method:: Decimal.to_integral([rounding[, context]]) .. method:: Decimal.to_integral([rounding[, context]])
@ -937,10 +937,10 @@ method. For example, ``C.exp(x)`` is equivalent to
change the result:: change the result::
>>> getcontext().prec = 3 >>> getcontext().prec = 3
>>> Decimal("3.4445") + Decimal("1.0023") >>> Decimal('3.4445') + Decimal('1.0023')
Decimal("4.45") Decimal('4.45')
>>> Decimal("3.4445") + Decimal(0) + Decimal("1.0023") >>> Decimal('3.4445') + Decimal(0) + Decimal('1.0023')
Decimal("4.44") Decimal('4.44')
This method implements the to-number operation of the IBM This method implements the to-number operation of the IBM
specification. If the argument is a string, no leading or trailing specification. If the argument is a string, no leading or trailing
@ -1195,15 +1195,15 @@ properties of addition::
>>> u, v, w = Decimal(11111113), Decimal(-11111111), Decimal('7.51111111') >>> u, v, w = Decimal(11111113), Decimal(-11111111), Decimal('7.51111111')
>>> (u + v) + w >>> (u + v) + w
Decimal("9.5111111") Decimal('9.5111111')
>>> u + (v + w) >>> u + (v + w)
Decimal("10") Decimal('10')
>>> u, v, w = Decimal(20000), Decimal(-6), Decimal('6.0000003') >>> u, v, w = Decimal(20000), Decimal(-6), Decimal('6.0000003')
>>> (u*v) + (u*w) >>> (u*v) + (u*w)
Decimal("0.01") Decimal('0.01')
>>> u * (v+w) >>> u * (v+w)
Decimal("0.0060000") Decimal('0.0060000')
The :mod:`decimal` module makes it possible to restore the identities by The :mod:`decimal` module makes it possible to restore the identities by
expanding the precision sufficiently to avoid loss of significance:: expanding the precision sufficiently to avoid loss of significance::
@ -1211,15 +1211,15 @@ expanding the precision sufficiently to avoid loss of significance::
>>> getcontext().prec = 20 >>> getcontext().prec = 20
>>> u, v, w = Decimal(11111113), Decimal(-11111111), Decimal('7.51111111') >>> u, v, w = Decimal(11111113), Decimal(-11111111), Decimal('7.51111111')
>>> (u + v) + w >>> (u + v) + w
Decimal("9.51111111") Decimal('9.51111111')
>>> u + (v + w) >>> u + (v + w)
Decimal("9.51111111") Decimal('9.51111111')
>>> >>>
>>> u, v, w = Decimal(20000), Decimal(-6), Decimal('6.0000003') >>> u, v, w = Decimal(20000), Decimal(-6), Decimal('6.0000003')
>>> (u*v) + (u*w) >>> (u*v) + (u*w)
Decimal("0.0060000") Decimal('0.0060000')
>>> u * (v+w) >>> u * (v+w)
Decimal("0.0060000") Decimal('0.0060000')
Special values Special values
@ -1275,7 +1275,7 @@ normalized floating point representations, it is not immediately obvious that
the following calculation returns a value equal to zero:: the following calculation returns a value equal to zero::
>>> 1 / Decimal('Infinity') >>> 1 / Decimal('Infinity')
Decimal("0E-1000000026") Decimal('0E-1000000026')
.. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% .. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -1486,7 +1486,7 @@ minimize typing when using the interactive interpreter?
>>> D = decimal.Decimal >>> D = decimal.Decimal
>>> D('1.23') + D('3.45') >>> D('1.23') + D('3.45')
Decimal("4.68") Decimal('4.68')
Q. In a fixed-point application with two decimal places, some inputs have many Q. In a fixed-point application with two decimal places, some inputs have many
places and need to be rounded. Others are not supposed to have excess digits places and need to be rounded. Others are not supposed to have excess digits
@ -1498,14 +1498,14 @@ the :const:`Inexact` trap is set, it is also useful for validation::
>>> TWOPLACES = Decimal(10) ** -2 # same as Decimal('0.01') >>> TWOPLACES = Decimal(10) ** -2 # same as Decimal('0.01')
>>> # Round to two places >>> # Round to two places
>>> Decimal("3.214").quantize(TWOPLACES) >>> Decimal('3.214').quantize(TWOPLACES)
Decimal("3.21") Decimal('3.21')
>>> # Validate that a number does not exceed two places >>> # Validate that a number does not exceed two places
>>> Decimal("3.21").quantize(TWOPLACES, context=Context(traps=[Inexact])) >>> Decimal('3.21').quantize(TWOPLACES, context=Context(traps=[Inexact]))
Decimal("3.21") Decimal('3.21')
>>> Decimal("3.214").quantize(TWOPLACES, context=Context(traps=[Inexact])) >>> Decimal('3.214').quantize(TWOPLACES, context=Context(traps=[Inexact]))
Traceback (most recent call last): Traceback (most recent call last):
... ...
Inexact: Changed in rounding Inexact: Changed in rounding
@ -1527,7 +1527,7 @@ representative::
>>> values = map(Decimal, '200 200.000 2E2 .02E+4'.split()) >>> values = map(Decimal, '200 200.000 2E2 .02E+4'.split())
>>> [v.normalize() for v in values] >>> [v.normalize() for v in values]
[Decimal("2E+2"), Decimal("2E+2"), Decimal("2E+2"), Decimal("2E+2")] [Decimal('2E+2'), Decimal('2E+2'), Decimal('2E+2'), Decimal('2E+2')]
Q. Some decimal values always print with exponential notation. Is there a way Q. Some decimal values always print with exponential notation. Is there a way
to get a non-exponential representation? to get a non-exponential representation?
@ -1555,7 +1555,7 @@ suggest, so we trap :const:`Inexact` to signal a need for more precision::
ctx.prec += 1 ctx.prec += 1
>>> float_to_decimal(math.pi) >>> float_to_decimal(math.pi)
Decimal("3.141592653589793115997963468544185161590576171875") Decimal('3.141592653589793115997963468544185161590576171875')
Q. Why isn't the :func:`float_to_decimal` routine included in the module? Q. Why isn't the :func:`float_to_decimal` routine included in the module?
@ -1564,7 +1564,7 @@ decimal floating point. Also, its use requires some care to avoid the
representation issues associated with binary floating point:: representation issues associated with binary floating point::
>>> float_to_decimal(1.1) >>> float_to_decimal(1.1)
Decimal("1.100000000000000088817841970012523233890533447265625") Decimal('1.100000000000000088817841970012523233890533447265625')
Q. Within a complex calculation, how can I make sure that I haven't gotten a Q. Within a complex calculation, how can I make sure that I haven't gotten a
spurious result because of insufficient precision or rounding anomalies. spurious result because of insufficient precision or rounding anomalies.
@ -1585,20 +1585,20 @@ results can look odd if you forget that the inputs haven't been rounded::
>>> getcontext().prec = 3 >>> getcontext().prec = 3
>>> Decimal('3.104') + D('2.104') >>> Decimal('3.104') + D('2.104')
Decimal("5.21") Decimal('5.21')
>>> Decimal('3.104') + D('0.000') + D('2.104') >>> Decimal('3.104') + D('0.000') + D('2.104')
Decimal("5.20") Decimal('5.20')
The solution is either to increase precision or to force rounding of inputs The solution is either to increase precision or to force rounding of inputs
using the unary plus operation:: using the unary plus operation::
>>> getcontext().prec = 3 >>> getcontext().prec = 3
>>> +Decimal('1.23456789') # unary plus triggers rounding >>> +Decimal('1.23456789') # unary plus triggers rounding
Decimal("1.23") Decimal('1.23')
Alternatively, inputs can be rounded upon creation using the Alternatively, inputs can be rounded upon creation using the
:meth:`Context.create_decimal` method:: :meth:`Context.create_decimal` method::
>>> Context(prec=5, rounding=ROUND_DOWN).create_decimal('1.2345678') >>> Context(prec=5, rounding=ROUND_DOWN).create_decimal('1.2345678')
Decimal("1.2345") Decimal('1.2345')

View File

@ -46,6 +46,24 @@ Rational number class.
:class:`decimal.Decimal`. :class:`decimal.Decimal`.
.. method:: Fraction.limit_denominator(max_denominator=1000000)
Finds and returns the closest :class:`Fraction` to ``self`` that
has denominator at most max_denominator. This method is useful for
finding rational approximations to a given floating-point number::
>>> Fraction('3.1415926535897932').limit_denominator(1000)
Fraction(355, 113)
or for recovering a rational number that's represented as a float::
>>> from math import pi, cos
>>> Fraction.from_float(cos(pi/3))
Fraction(4503599627370497L, 9007199254740992L)
>>> Fraction.from_float(cos(pi/3)).limit_denominator()
Fraction(1, 2)
.. method:: Fraction.__floor__() .. method:: Fraction.__floor__()
Returns the greatest :class:`int` ``<= self``. Will be accessible Returns the greatest :class:`int` ``<= self``. Will be accessible

View File

@ -1584,7 +1584,7 @@ written in Python, such as a mail server's external command delivery program.
user time, children's system time, and elapsed real time since a fixed point in user time, children's system time, and elapsed real time since a fixed point in
the past, in that order. See the Unix manual page :manpage:`times(2)` or the the past, in that order. See the Unix manual page :manpage:`times(2)` or the
corresponding Windows Platform API documentation. Availability: Macintosh, Unix, corresponding Windows Platform API documentation. Availability: Macintosh, Unix,
Windows. Windows. On Windows, only the first two items are filled, the others are zero.
.. function:: wait() .. function:: wait()

View File

@ -162,8 +162,19 @@ class ABCMeta(type):
def __instancecheck__(cls, instance): def __instancecheck__(cls, instance):
"""Override for isinstance(instance, cls).""" """Override for isinstance(instance, cls)."""
return any(cls.__subclasscheck__(c) # Inline the cache checking
for c in {instance.__class__, type(instance)}) subclass = instance.__class__
if subclass in cls._abc_cache:
return True
subtype = type(instance)
if subtype is subclass:
if (cls._abc_negative_cache_version ==
ABCMeta._abc_invalidation_counter and
subclass in cls._abc_negative_cache):
return False
# Fall back to the subclass check.
return cls.__subclasscheck__(subclass)
return any(cls.__subclasscheck__(c) for c in {subclass, subtype})
def __subclasscheck__(cls, subclass): def __subclasscheck__(cls, subclass):
"""Override for issubclass(subclass, cls).""" """Override for issubclass(subclass, cls)."""

View File

@ -35,26 +35,26 @@ issues associated with binary floating point. The package is especially
useful for financial applications or for contexts where users have useful for financial applications or for contexts where users have
expectations that are at odds with binary floating point (for instance, expectations that are at odds with binary floating point (for instance,
in binary floating point, 1.00 % 0.1 gives 0.09999999999999995 instead in binary floating point, 1.00 % 0.1 gives 0.09999999999999995 instead
of the expected Decimal("0.00") returned by decimal floating point). of the expected Decimal('0.00') returned by decimal floating point).
Here are some examples of using the decimal module: Here are some examples of using the decimal module:
>>> from decimal import * >>> from decimal import *
>>> setcontext(ExtendedContext) >>> setcontext(ExtendedContext)
>>> Decimal(0) >>> Decimal(0)
Decimal("0") Decimal('0')
>>> Decimal("1") >>> Decimal('1')
Decimal("1") Decimal('1')
>>> Decimal("-.0123") >>> Decimal('-.0123')
Decimal("-0.0123") Decimal('-0.0123')
>>> Decimal(123456) >>> Decimal(123456)
Decimal("123456") Decimal('123456')
>>> Decimal("123.45e12345678901234567890") >>> Decimal('123.45e12345678901234567890')
Decimal("1.2345E+12345678901234567892") Decimal('1.2345E+12345678901234567892')
>>> Decimal("1.33") + Decimal("1.27") >>> Decimal('1.33') + Decimal('1.27')
Decimal("2.60") Decimal('2.60')
>>> Decimal("12.34") + Decimal("3.87") - Decimal("18.41") >>> Decimal('12.34') + Decimal('3.87') - Decimal('18.41')
Decimal("-2.20") Decimal('-2.20')
>>> dig = Decimal(1) >>> dig = Decimal(1)
>>> print(dig / Decimal(3)) >>> print(dig / Decimal(3))
0.333333333 0.333333333
@ -91,7 +91,7 @@ decimal.DivisionByZero: x / 0
>>> print(c.flags[InvalidOperation]) >>> print(c.flags[InvalidOperation])
0 0
>>> c.divide(Decimal(0), Decimal(0)) >>> c.divide(Decimal(0), Decimal(0))
Decimal("NaN") Decimal('NaN')
>>> c.traps[InvalidOperation] = 1 >>> c.traps[InvalidOperation] = 1
>>> print(c.flags[InvalidOperation]) >>> print(c.flags[InvalidOperation])
1 1
@ -517,15 +517,15 @@ class Decimal(_numbers.Real, _numbers.Inexact):
"""Create a decimal point instance. """Create a decimal point instance.
>>> Decimal('3.14') # string input >>> Decimal('3.14') # string input
Decimal("3.14") Decimal('3.14')
>>> Decimal((0, (3, 1, 4), -2)) # tuple (sign, digit_tuple, exponent) >>> Decimal((0, (3, 1, 4), -2)) # tuple (sign, digit_tuple, exponent)
Decimal("3.14") Decimal('3.14')
>>> Decimal(314) # int >>> Decimal(314) # int
Decimal("314") Decimal('314')
>>> Decimal(Decimal(314)) # another decimal instance >>> Decimal(Decimal(314)) # another decimal instance
Decimal("314") Decimal('314')
>>> Decimal(' 3.14 \\n') # leading and trailing whitespace okay >>> Decimal(' 3.14 \\n') # leading and trailing whitespace okay
Decimal("3.14") Decimal('3.14')
""" """
# Note that the coefficient, self._int, is actually stored as # Note that the coefficient, self._int, is actually stored as
@ -885,7 +885,7 @@ class Decimal(_numbers.Real, _numbers.Inexact):
# #
# The hash of a nonspecial noninteger Decimal must depend only # The hash of a nonspecial noninteger Decimal must depend only
# on the value of that Decimal, and not on its representation. # on the value of that Decimal, and not on its representation.
# For example: hash(Decimal("100E-1")) == hash(Decimal("10")). # For example: hash(Decimal('100E-1')) == hash(Decimal('10')).
if self._is_special: if self._is_special:
if self._isnan(): if self._isnan():
raise TypeError('Cannot hash a NaN value.') raise TypeError('Cannot hash a NaN value.')
@ -919,7 +919,7 @@ class Decimal(_numbers.Real, _numbers.Inexact):
def __repr__(self): def __repr__(self):
"""Represents the number as an instance of Decimal.""" """Represents the number as an instance of Decimal."""
# Invariant: eval(repr(d)) == d # Invariant: eval(repr(d)) == d
return 'Decimal("%s")' % str(self) return "Decimal('%s')" % str(self)
def __str__(self, eng=False, context=None): def __str__(self, eng=False, context=None):
"""Return string representation of the number in scientific notation. """Return string representation of the number in scientific notation.
@ -3637,13 +3637,13 @@ class Context(object):
the plus operation on the operand. the plus operation on the operand.
>>> ExtendedContext.abs(Decimal('2.1')) >>> ExtendedContext.abs(Decimal('2.1'))
Decimal("2.1") Decimal('2.1')
>>> ExtendedContext.abs(Decimal('-100')) >>> ExtendedContext.abs(Decimal('-100'))
Decimal("100") Decimal('100')
>>> ExtendedContext.abs(Decimal('101.5')) >>> ExtendedContext.abs(Decimal('101.5'))
Decimal("101.5") Decimal('101.5')
>>> ExtendedContext.abs(Decimal('-101.5')) >>> ExtendedContext.abs(Decimal('-101.5'))
Decimal("101.5") Decimal('101.5')
""" """
return a.__abs__(context=self) return a.__abs__(context=self)
@ -3651,9 +3651,9 @@ class Context(object):
"""Return the sum of the two operands. """Return the sum of the two operands.
>>> ExtendedContext.add(Decimal('12'), Decimal('7.00')) >>> ExtendedContext.add(Decimal('12'), Decimal('7.00'))
Decimal("19.00") Decimal('19.00')
>>> ExtendedContext.add(Decimal('1E+2'), Decimal('1.01E+4')) >>> ExtendedContext.add(Decimal('1E+2'), Decimal('1.01E+4'))
Decimal("1.02E+4") Decimal('1.02E+4')
""" """
return a.__add__(b, context=self) return a.__add__(b, context=self)
@ -3667,7 +3667,7 @@ class Context(object):
received object already is in its canonical form. received object already is in its canonical form.
>>> ExtendedContext.canonical(Decimal('2.50')) >>> ExtendedContext.canonical(Decimal('2.50'))
Decimal("2.50") Decimal('2.50')
""" """
return a.canonical(context=self) return a.canonical(context=self)
@ -3686,17 +3686,17 @@ class Context(object):
zero or negative zero, or '1' if the result is greater than zero. zero or negative zero, or '1' if the result is greater than zero.
>>> ExtendedContext.compare(Decimal('2.1'), Decimal('3')) >>> ExtendedContext.compare(Decimal('2.1'), Decimal('3'))
Decimal("-1") Decimal('-1')
>>> ExtendedContext.compare(Decimal('2.1'), Decimal('2.1')) >>> ExtendedContext.compare(Decimal('2.1'), Decimal('2.1'))
Decimal("0") Decimal('0')
>>> ExtendedContext.compare(Decimal('2.1'), Decimal('2.10')) >>> ExtendedContext.compare(Decimal('2.1'), Decimal('2.10'))
Decimal("0") Decimal('0')
>>> ExtendedContext.compare(Decimal('3'), Decimal('2.1')) >>> ExtendedContext.compare(Decimal('3'), Decimal('2.1'))
Decimal("1") Decimal('1')
>>> ExtendedContext.compare(Decimal('2.1'), Decimal('-3')) >>> ExtendedContext.compare(Decimal('2.1'), Decimal('-3'))
Decimal("1") Decimal('1')
>>> ExtendedContext.compare(Decimal('-3'), Decimal('2.1')) >>> ExtendedContext.compare(Decimal('-3'), Decimal('2.1'))
Decimal("-1") Decimal('-1')
""" """
return a.compare(b, context=self) return a.compare(b, context=self)
@ -3708,21 +3708,21 @@ class Context(object):
>>> c = ExtendedContext >>> c = ExtendedContext
>>> c.compare_signal(Decimal('2.1'), Decimal('3')) >>> c.compare_signal(Decimal('2.1'), Decimal('3'))
Decimal("-1") Decimal('-1')
>>> c.compare_signal(Decimal('2.1'), Decimal('2.1')) >>> c.compare_signal(Decimal('2.1'), Decimal('2.1'))
Decimal("0") Decimal('0')
>>> c.flags[InvalidOperation] = 0 >>> c.flags[InvalidOperation] = 0
>>> print(c.flags[InvalidOperation]) >>> print(c.flags[InvalidOperation])
0 0
>>> c.compare_signal(Decimal('NaN'), Decimal('2.1')) >>> c.compare_signal(Decimal('NaN'), Decimal('2.1'))
Decimal("NaN") Decimal('NaN')
>>> print(c.flags[InvalidOperation]) >>> print(c.flags[InvalidOperation])
1 1
>>> c.flags[InvalidOperation] = 0 >>> c.flags[InvalidOperation] = 0
>>> print(c.flags[InvalidOperation]) >>> print(c.flags[InvalidOperation])
0 0
>>> c.compare_signal(Decimal('sNaN'), Decimal('2.1')) >>> c.compare_signal(Decimal('sNaN'), Decimal('2.1'))
Decimal("NaN") Decimal('NaN')
>>> print(c.flags[InvalidOperation]) >>> print(c.flags[InvalidOperation])
1 1
""" """
@ -3736,17 +3736,17 @@ class Context(object):
representations. representations.
>>> ExtendedContext.compare_total(Decimal('12.73'), Decimal('127.9')) >>> ExtendedContext.compare_total(Decimal('12.73'), Decimal('127.9'))
Decimal("-1") Decimal('-1')
>>> ExtendedContext.compare_total(Decimal('-127'), Decimal('12')) >>> ExtendedContext.compare_total(Decimal('-127'), Decimal('12'))
Decimal("-1") Decimal('-1')
>>> ExtendedContext.compare_total(Decimal('12.30'), Decimal('12.3')) >>> ExtendedContext.compare_total(Decimal('12.30'), Decimal('12.3'))
Decimal("-1") Decimal('-1')
>>> ExtendedContext.compare_total(Decimal('12.30'), Decimal('12.30')) >>> ExtendedContext.compare_total(Decimal('12.30'), Decimal('12.30'))
Decimal("0") Decimal('0')
>>> ExtendedContext.compare_total(Decimal('12.3'), Decimal('12.300')) >>> ExtendedContext.compare_total(Decimal('12.3'), Decimal('12.300'))
Decimal("1") Decimal('1')
>>> ExtendedContext.compare_total(Decimal('12.3'), Decimal('NaN')) >>> ExtendedContext.compare_total(Decimal('12.3'), Decimal('NaN'))
Decimal("-1") Decimal('-1')
""" """
return a.compare_total(b) return a.compare_total(b)
@ -3761,9 +3761,9 @@ class Context(object):
"""Returns a copy of the operand with the sign set to 0. """Returns a copy of the operand with the sign set to 0.
>>> ExtendedContext.copy_abs(Decimal('2.1')) >>> ExtendedContext.copy_abs(Decimal('2.1'))
Decimal("2.1") Decimal('2.1')
>>> ExtendedContext.copy_abs(Decimal('-100')) >>> ExtendedContext.copy_abs(Decimal('-100'))
Decimal("100") Decimal('100')
""" """
return a.copy_abs() return a.copy_abs()
@ -3771,9 +3771,9 @@ class Context(object):
"""Returns a copy of the decimal objet. """Returns a copy of the decimal objet.
>>> ExtendedContext.copy_decimal(Decimal('2.1')) >>> ExtendedContext.copy_decimal(Decimal('2.1'))
Decimal("2.1") Decimal('2.1')
>>> ExtendedContext.copy_decimal(Decimal('-1.00')) >>> ExtendedContext.copy_decimal(Decimal('-1.00'))
Decimal("-1.00") Decimal('-1.00')
""" """
return Decimal(a) return Decimal(a)
@ -3781,9 +3781,9 @@ class Context(object):
"""Returns a copy of the operand with the sign inverted. """Returns a copy of the operand with the sign inverted.
>>> ExtendedContext.copy_negate(Decimal('101.5')) >>> ExtendedContext.copy_negate(Decimal('101.5'))
Decimal("-101.5") Decimal('-101.5')
>>> ExtendedContext.copy_negate(Decimal('-101.5')) >>> ExtendedContext.copy_negate(Decimal('-101.5'))
Decimal("101.5") Decimal('101.5')
""" """
return a.copy_negate() return a.copy_negate()
@ -3794,13 +3794,13 @@ class Context(object):
equal to the sign of the second operand. equal to the sign of the second operand.
>>> ExtendedContext.copy_sign(Decimal( '1.50'), Decimal('7.33')) >>> ExtendedContext.copy_sign(Decimal( '1.50'), Decimal('7.33'))
Decimal("1.50") Decimal('1.50')
>>> ExtendedContext.copy_sign(Decimal('-1.50'), Decimal('7.33')) >>> ExtendedContext.copy_sign(Decimal('-1.50'), Decimal('7.33'))
Decimal("1.50") Decimal('1.50')
>>> ExtendedContext.copy_sign(Decimal( '1.50'), Decimal('-7.33')) >>> ExtendedContext.copy_sign(Decimal( '1.50'), Decimal('-7.33'))
Decimal("-1.50") Decimal('-1.50')
>>> ExtendedContext.copy_sign(Decimal('-1.50'), Decimal('-7.33')) >>> ExtendedContext.copy_sign(Decimal('-1.50'), Decimal('-7.33'))
Decimal("-1.50") Decimal('-1.50')
""" """
return a.copy_sign(b) return a.copy_sign(b)
@ -3808,25 +3808,25 @@ class Context(object):
"""Decimal division in a specified context. """Decimal division in a specified context.
>>> ExtendedContext.divide(Decimal('1'), Decimal('3')) >>> ExtendedContext.divide(Decimal('1'), Decimal('3'))
Decimal("0.333333333") Decimal('0.333333333')
>>> ExtendedContext.divide(Decimal('2'), Decimal('3')) >>> ExtendedContext.divide(Decimal('2'), Decimal('3'))
Decimal("0.666666667") Decimal('0.666666667')
>>> ExtendedContext.divide(Decimal('5'), Decimal('2')) >>> ExtendedContext.divide(Decimal('5'), Decimal('2'))
Decimal("2.5") Decimal('2.5')
>>> ExtendedContext.divide(Decimal('1'), Decimal('10')) >>> ExtendedContext.divide(Decimal('1'), Decimal('10'))
Decimal("0.1") Decimal('0.1')
>>> ExtendedContext.divide(Decimal('12'), Decimal('12')) >>> ExtendedContext.divide(Decimal('12'), Decimal('12'))
Decimal("1") Decimal('1')
>>> ExtendedContext.divide(Decimal('8.00'), Decimal('2')) >>> ExtendedContext.divide(Decimal('8.00'), Decimal('2'))
Decimal("4.00") Decimal('4.00')
>>> ExtendedContext.divide(Decimal('2.400'), Decimal('2.0')) >>> ExtendedContext.divide(Decimal('2.400'), Decimal('2.0'))
Decimal("1.20") Decimal('1.20')
>>> ExtendedContext.divide(Decimal('1000'), Decimal('100')) >>> ExtendedContext.divide(Decimal('1000'), Decimal('100'))
Decimal("10") Decimal('10')
>>> ExtendedContext.divide(Decimal('1000'), Decimal('1')) >>> ExtendedContext.divide(Decimal('1000'), Decimal('1'))
Decimal("1000") Decimal('1000')
>>> ExtendedContext.divide(Decimal('2.40E+6'), Decimal('2')) >>> ExtendedContext.divide(Decimal('2.40E+6'), Decimal('2'))
Decimal("1.20E+6") Decimal('1.20E+6')
""" """
return a.__truediv__(b, context=self) return a.__truediv__(b, context=self)
@ -3834,11 +3834,11 @@ class Context(object):
"""Divides two numbers and returns the integer part of the result. """Divides two numbers and returns the integer part of the result.
>>> ExtendedContext.divide_int(Decimal('2'), Decimal('3')) >>> ExtendedContext.divide_int(Decimal('2'), Decimal('3'))
Decimal("0") Decimal('0')
>>> ExtendedContext.divide_int(Decimal('10'), Decimal('3')) >>> ExtendedContext.divide_int(Decimal('10'), Decimal('3'))
Decimal("3") Decimal('3')
>>> ExtendedContext.divide_int(Decimal('1'), Decimal('0.3')) >>> ExtendedContext.divide_int(Decimal('1'), Decimal('0.3'))
Decimal("3") Decimal('3')
""" """
return a.__floordiv__(b, context=self) return a.__floordiv__(b, context=self)
@ -3852,17 +3852,17 @@ class Context(object):
>>> c.Emin = -999 >>> c.Emin = -999
>>> c.Emax = 999 >>> c.Emax = 999
>>> c.exp(Decimal('-Infinity')) >>> c.exp(Decimal('-Infinity'))
Decimal("0") Decimal('0')
>>> c.exp(Decimal('-1')) >>> c.exp(Decimal('-1'))
Decimal("0.367879441") Decimal('0.367879441')
>>> c.exp(Decimal('0')) >>> c.exp(Decimal('0'))
Decimal("1") Decimal('1')
>>> c.exp(Decimal('1')) >>> c.exp(Decimal('1'))
Decimal("2.71828183") Decimal('2.71828183')
>>> c.exp(Decimal('0.693147181')) >>> c.exp(Decimal('0.693147181'))
Decimal("2.00000000") Decimal('2.00000000')
>>> c.exp(Decimal('+Infinity')) >>> c.exp(Decimal('+Infinity'))
Decimal("Infinity") Decimal('Infinity')
""" """
return a.exp(context=self) return a.exp(context=self)
@ -3874,11 +3874,11 @@ class Context(object):
multiplication, using add, all with only one final rounding. multiplication, using add, all with only one final rounding.
>>> ExtendedContext.fma(Decimal('3'), Decimal('5'), Decimal('7')) >>> ExtendedContext.fma(Decimal('3'), Decimal('5'), Decimal('7'))
Decimal("22") Decimal('22')
>>> ExtendedContext.fma(Decimal('3'), Decimal('-5'), Decimal('7')) >>> ExtendedContext.fma(Decimal('3'), Decimal('-5'), Decimal('7'))
Decimal("-8") Decimal('-8')
>>> ExtendedContext.fma(Decimal('888565290'), Decimal('1557.96930'), Decimal('-86087.7578')) >>> ExtendedContext.fma(Decimal('888565290'), Decimal('1557.96930'), Decimal('-86087.7578'))
Decimal("1.38435736E+12") Decimal('1.38435736E+12')
""" """
return a.fma(b, c, context=self) return a.fma(b, c, context=self)
@ -4032,15 +4032,15 @@ class Context(object):
>>> c.Emin = -999 >>> c.Emin = -999
>>> c.Emax = 999 >>> c.Emax = 999
>>> c.ln(Decimal('0')) >>> c.ln(Decimal('0'))
Decimal("-Infinity") Decimal('-Infinity')
>>> c.ln(Decimal('1.000')) >>> c.ln(Decimal('1.000'))
Decimal("0") Decimal('0')
>>> c.ln(Decimal('2.71828183')) >>> c.ln(Decimal('2.71828183'))
Decimal("1.00000000") Decimal('1.00000000')
>>> c.ln(Decimal('10')) >>> c.ln(Decimal('10'))
Decimal("2.30258509") Decimal('2.30258509')
>>> c.ln(Decimal('+Infinity')) >>> c.ln(Decimal('+Infinity'))
Decimal("Infinity") Decimal('Infinity')
""" """
return a.ln(context=self) return a.ln(context=self)
@ -4051,19 +4051,19 @@ class Context(object):
>>> c.Emin = -999 >>> c.Emin = -999
>>> c.Emax = 999 >>> c.Emax = 999
>>> c.log10(Decimal('0')) >>> c.log10(Decimal('0'))
Decimal("-Infinity") Decimal('-Infinity')
>>> c.log10(Decimal('0.001')) >>> c.log10(Decimal('0.001'))
Decimal("-3") Decimal('-3')
>>> c.log10(Decimal('1.000')) >>> c.log10(Decimal('1.000'))
Decimal("0") Decimal('0')
>>> c.log10(Decimal('2')) >>> c.log10(Decimal('2'))
Decimal("0.301029996") Decimal('0.301029996')
>>> c.log10(Decimal('10')) >>> c.log10(Decimal('10'))
Decimal("1") Decimal('1')
>>> c.log10(Decimal('70')) >>> c.log10(Decimal('70'))
Decimal("1.84509804") Decimal('1.84509804')
>>> c.log10(Decimal('+Infinity')) >>> c.log10(Decimal('+Infinity'))
Decimal("Infinity") Decimal('Infinity')
""" """
return a.log10(context=self) return a.log10(context=self)
@ -4076,13 +4076,13 @@ class Context(object):
value of that digit and without limiting the resulting exponent). value of that digit and without limiting the resulting exponent).
>>> ExtendedContext.logb(Decimal('250')) >>> ExtendedContext.logb(Decimal('250'))
Decimal("2") Decimal('2')
>>> ExtendedContext.logb(Decimal('2.50')) >>> ExtendedContext.logb(Decimal('2.50'))
Decimal("0") Decimal('0')
>>> ExtendedContext.logb(Decimal('0.03')) >>> ExtendedContext.logb(Decimal('0.03'))
Decimal("-2") Decimal('-2')
>>> ExtendedContext.logb(Decimal('0')) >>> ExtendedContext.logb(Decimal('0'))
Decimal("-Infinity") Decimal('-Infinity')
""" """
return a.logb(context=self) return a.logb(context=self)
@ -4092,17 +4092,17 @@ class Context(object):
The operands must be both logical numbers. The operands must be both logical numbers.
>>> ExtendedContext.logical_and(Decimal('0'), Decimal('0')) >>> ExtendedContext.logical_and(Decimal('0'), Decimal('0'))
Decimal("0") Decimal('0')
>>> ExtendedContext.logical_and(Decimal('0'), Decimal('1')) >>> ExtendedContext.logical_and(Decimal('0'), Decimal('1'))
Decimal("0") Decimal('0')
>>> ExtendedContext.logical_and(Decimal('1'), Decimal('0')) >>> ExtendedContext.logical_and(Decimal('1'), Decimal('0'))
Decimal("0") Decimal('0')
>>> ExtendedContext.logical_and(Decimal('1'), Decimal('1')) >>> ExtendedContext.logical_and(Decimal('1'), Decimal('1'))
Decimal("1") Decimal('1')
>>> ExtendedContext.logical_and(Decimal('1100'), Decimal('1010')) >>> ExtendedContext.logical_and(Decimal('1100'), Decimal('1010'))
Decimal("1000") Decimal('1000')
>>> ExtendedContext.logical_and(Decimal('1111'), Decimal('10')) >>> ExtendedContext.logical_and(Decimal('1111'), Decimal('10'))
Decimal("10") Decimal('10')
""" """
return a.logical_and(b, context=self) return a.logical_and(b, context=self)
@ -4112,13 +4112,13 @@ class Context(object):
The operand must be a logical number. The operand must be a logical number.
>>> ExtendedContext.logical_invert(Decimal('0')) >>> ExtendedContext.logical_invert(Decimal('0'))
Decimal("111111111") Decimal('111111111')
>>> ExtendedContext.logical_invert(Decimal('1')) >>> ExtendedContext.logical_invert(Decimal('1'))
Decimal("111111110") Decimal('111111110')
>>> ExtendedContext.logical_invert(Decimal('111111111')) >>> ExtendedContext.logical_invert(Decimal('111111111'))
Decimal("0") Decimal('0')
>>> ExtendedContext.logical_invert(Decimal('101010101')) >>> ExtendedContext.logical_invert(Decimal('101010101'))
Decimal("10101010") Decimal('10101010')
""" """
return a.logical_invert(context=self) return a.logical_invert(context=self)
@ -4128,17 +4128,17 @@ class Context(object):
The operands must be both logical numbers. The operands must be both logical numbers.
>>> ExtendedContext.logical_or(Decimal('0'), Decimal('0')) >>> ExtendedContext.logical_or(Decimal('0'), Decimal('0'))
Decimal("0") Decimal('0')
>>> ExtendedContext.logical_or(Decimal('0'), Decimal('1')) >>> ExtendedContext.logical_or(Decimal('0'), Decimal('1'))
Decimal("1") Decimal('1')
>>> ExtendedContext.logical_or(Decimal('1'), Decimal('0')) >>> ExtendedContext.logical_or(Decimal('1'), Decimal('0'))
Decimal("1") Decimal('1')
>>> ExtendedContext.logical_or(Decimal('1'), Decimal('1')) >>> ExtendedContext.logical_or(Decimal('1'), Decimal('1'))
Decimal("1") Decimal('1')
>>> ExtendedContext.logical_or(Decimal('1100'), Decimal('1010')) >>> ExtendedContext.logical_or(Decimal('1100'), Decimal('1010'))
Decimal("1110") Decimal('1110')
>>> ExtendedContext.logical_or(Decimal('1110'), Decimal('10')) >>> ExtendedContext.logical_or(Decimal('1110'), Decimal('10'))
Decimal("1110") Decimal('1110')
""" """
return a.logical_or(b, context=self) return a.logical_or(b, context=self)
@ -4148,17 +4148,17 @@ class Context(object):
The operands must be both logical numbers. The operands must be both logical numbers.
>>> ExtendedContext.logical_xor(Decimal('0'), Decimal('0')) >>> ExtendedContext.logical_xor(Decimal('0'), Decimal('0'))
Decimal("0") Decimal('0')
>>> ExtendedContext.logical_xor(Decimal('0'), Decimal('1')) >>> ExtendedContext.logical_xor(Decimal('0'), Decimal('1'))
Decimal("1") Decimal('1')
>>> ExtendedContext.logical_xor(Decimal('1'), Decimal('0')) >>> ExtendedContext.logical_xor(Decimal('1'), Decimal('0'))
Decimal("1") Decimal('1')
>>> ExtendedContext.logical_xor(Decimal('1'), Decimal('1')) >>> ExtendedContext.logical_xor(Decimal('1'), Decimal('1'))
Decimal("0") Decimal('0')
>>> ExtendedContext.logical_xor(Decimal('1100'), Decimal('1010')) >>> ExtendedContext.logical_xor(Decimal('1100'), Decimal('1010'))
Decimal("110") Decimal('110')
>>> ExtendedContext.logical_xor(Decimal('1111'), Decimal('10')) >>> ExtendedContext.logical_xor(Decimal('1111'), Decimal('10'))
Decimal("1101") Decimal('1101')
""" """
return a.logical_xor(b, context=self) return a.logical_xor(b, context=self)
@ -4172,13 +4172,13 @@ class Context(object):
infinity) of the two operands is chosen as the result. infinity) of the two operands is chosen as the result.
>>> ExtendedContext.max(Decimal('3'), Decimal('2')) >>> ExtendedContext.max(Decimal('3'), Decimal('2'))
Decimal("3") Decimal('3')
>>> ExtendedContext.max(Decimal('-10'), Decimal('3')) >>> ExtendedContext.max(Decimal('-10'), Decimal('3'))
Decimal("3") Decimal('3')
>>> ExtendedContext.max(Decimal('1.0'), Decimal('1')) >>> ExtendedContext.max(Decimal('1.0'), Decimal('1'))
Decimal("1") Decimal('1')
>>> ExtendedContext.max(Decimal('7'), Decimal('NaN')) >>> ExtendedContext.max(Decimal('7'), Decimal('NaN'))
Decimal("7") Decimal('7')
""" """
return a.max(b, context=self) return a.max(b, context=self)
@ -4196,13 +4196,13 @@ class Context(object):
infinity) of the two operands is chosen as the result. infinity) of the two operands is chosen as the result.
>>> ExtendedContext.min(Decimal('3'), Decimal('2')) >>> ExtendedContext.min(Decimal('3'), Decimal('2'))
Decimal("2") Decimal('2')
>>> ExtendedContext.min(Decimal('-10'), Decimal('3')) >>> ExtendedContext.min(Decimal('-10'), Decimal('3'))
Decimal("-10") Decimal('-10')
>>> ExtendedContext.min(Decimal('1.0'), Decimal('1')) >>> ExtendedContext.min(Decimal('1.0'), Decimal('1'))
Decimal("1.0") Decimal('1.0')
>>> ExtendedContext.min(Decimal('7'), Decimal('NaN')) >>> ExtendedContext.min(Decimal('7'), Decimal('NaN'))
Decimal("7") Decimal('7')
""" """
return a.min(b, context=self) return a.min(b, context=self)
@ -4218,9 +4218,9 @@ class Context(object):
has the same exponent as the operand. has the same exponent as the operand.
>>> ExtendedContext.minus(Decimal('1.3')) >>> ExtendedContext.minus(Decimal('1.3'))
Decimal("-1.3") Decimal('-1.3')
>>> ExtendedContext.minus(Decimal('-1.3')) >>> ExtendedContext.minus(Decimal('-1.3'))
Decimal("1.3") Decimal('1.3')
""" """
return a.__neg__(context=self) return a.__neg__(context=self)
@ -4233,15 +4233,15 @@ class Context(object):
of the two operands. of the two operands.
>>> ExtendedContext.multiply(Decimal('1.20'), Decimal('3')) >>> ExtendedContext.multiply(Decimal('1.20'), Decimal('3'))
Decimal("3.60") Decimal('3.60')
>>> ExtendedContext.multiply(Decimal('7'), Decimal('3')) >>> ExtendedContext.multiply(Decimal('7'), Decimal('3'))
Decimal("21") Decimal('21')
>>> ExtendedContext.multiply(Decimal('0.9'), Decimal('0.8')) >>> ExtendedContext.multiply(Decimal('0.9'), Decimal('0.8'))
Decimal("0.72") Decimal('0.72')
>>> ExtendedContext.multiply(Decimal('0.9'), Decimal('-0')) >>> ExtendedContext.multiply(Decimal('0.9'), Decimal('-0'))
Decimal("-0.0") Decimal('-0.0')
>>> ExtendedContext.multiply(Decimal('654321'), Decimal('654321')) >>> ExtendedContext.multiply(Decimal('654321'), Decimal('654321'))
Decimal("4.28135971E+11") Decimal('4.28135971E+11')
""" """
return a.__mul__(b, context=self) return a.__mul__(b, context=self)
@ -4252,13 +4252,13 @@ class Context(object):
>>> c.Emin = -999 >>> c.Emin = -999
>>> c.Emax = 999 >>> c.Emax = 999
>>> ExtendedContext.next_minus(Decimal('1')) >>> ExtendedContext.next_minus(Decimal('1'))
Decimal("0.999999999") Decimal('0.999999999')
>>> c.next_minus(Decimal('1E-1007')) >>> c.next_minus(Decimal('1E-1007'))
Decimal("0E-1007") Decimal('0E-1007')
>>> ExtendedContext.next_minus(Decimal('-1.00000003')) >>> ExtendedContext.next_minus(Decimal('-1.00000003'))
Decimal("-1.00000004") Decimal('-1.00000004')
>>> c.next_minus(Decimal('Infinity')) >>> c.next_minus(Decimal('Infinity'))
Decimal("9.99999999E+999") Decimal('9.99999999E+999')
""" """
return a.next_minus(context=self) return a.next_minus(context=self)
@ -4269,13 +4269,13 @@ class Context(object):
>>> c.Emin = -999 >>> c.Emin = -999
>>> c.Emax = 999 >>> c.Emax = 999
>>> ExtendedContext.next_plus(Decimal('1')) >>> ExtendedContext.next_plus(Decimal('1'))
Decimal("1.00000001") Decimal('1.00000001')
>>> c.next_plus(Decimal('-1E-1007')) >>> c.next_plus(Decimal('-1E-1007'))
Decimal("-0E-1007") Decimal('-0E-1007')
>>> ExtendedContext.next_plus(Decimal('-1.00000003')) >>> ExtendedContext.next_plus(Decimal('-1.00000003'))
Decimal("-1.00000002") Decimal('-1.00000002')
>>> c.next_plus(Decimal('-Infinity')) >>> c.next_plus(Decimal('-Infinity'))
Decimal("-9.99999999E+999") Decimal('-9.99999999E+999')
""" """
return a.next_plus(context=self) return a.next_plus(context=self)
@ -4291,19 +4291,19 @@ class Context(object):
>>> c.Emin = -999 >>> c.Emin = -999
>>> c.Emax = 999 >>> c.Emax = 999
>>> c.next_toward(Decimal('1'), Decimal('2')) >>> c.next_toward(Decimal('1'), Decimal('2'))
Decimal("1.00000001") Decimal('1.00000001')
>>> c.next_toward(Decimal('-1E-1007'), Decimal('1')) >>> c.next_toward(Decimal('-1E-1007'), Decimal('1'))
Decimal("-0E-1007") Decimal('-0E-1007')
>>> c.next_toward(Decimal('-1.00000003'), Decimal('0')) >>> c.next_toward(Decimal('-1.00000003'), Decimal('0'))
Decimal("-1.00000002") Decimal('-1.00000002')
>>> c.next_toward(Decimal('1'), Decimal('0')) >>> c.next_toward(Decimal('1'), Decimal('0'))
Decimal("0.999999999") Decimal('0.999999999')
>>> c.next_toward(Decimal('1E-1007'), Decimal('-100')) >>> c.next_toward(Decimal('1E-1007'), Decimal('-100'))
Decimal("0E-1007") Decimal('0E-1007')
>>> c.next_toward(Decimal('-1.00000003'), Decimal('-10')) >>> c.next_toward(Decimal('-1.00000003'), Decimal('-10'))
Decimal("-1.00000004") Decimal('-1.00000004')
>>> c.next_toward(Decimal('0.00'), Decimal('-0.0000')) >>> c.next_toward(Decimal('0.00'), Decimal('-0.0000'))
Decimal("-0.00") Decimal('-0.00')
""" """
return a.next_toward(b, context=self) return a.next_toward(b, context=self)
@ -4314,17 +4314,17 @@ class Context(object):
result. result.
>>> ExtendedContext.normalize(Decimal('2.1')) >>> ExtendedContext.normalize(Decimal('2.1'))
Decimal("2.1") Decimal('2.1')
>>> ExtendedContext.normalize(Decimal('-2.0')) >>> ExtendedContext.normalize(Decimal('-2.0'))
Decimal("-2") Decimal('-2')
>>> ExtendedContext.normalize(Decimal('1.200')) >>> ExtendedContext.normalize(Decimal('1.200'))
Decimal("1.2") Decimal('1.2')
>>> ExtendedContext.normalize(Decimal('-120')) >>> ExtendedContext.normalize(Decimal('-120'))
Decimal("-1.2E+2") Decimal('-1.2E+2')
>>> ExtendedContext.normalize(Decimal('120.00')) >>> ExtendedContext.normalize(Decimal('120.00'))
Decimal("1.2E+2") Decimal('1.2E+2')
>>> ExtendedContext.normalize(Decimal('0.00')) >>> ExtendedContext.normalize(Decimal('0.00'))
Decimal("0") Decimal('0')
""" """
return a.normalize(context=self) return a.normalize(context=self)
@ -4383,9 +4383,9 @@ class Context(object):
has the same exponent as the operand. has the same exponent as the operand.
>>> ExtendedContext.plus(Decimal('1.3')) >>> ExtendedContext.plus(Decimal('1.3'))
Decimal("1.3") Decimal('1.3')
>>> ExtendedContext.plus(Decimal('-1.3')) >>> ExtendedContext.plus(Decimal('-1.3'))
Decimal("-1.3") Decimal('-1.3')
""" """
return a.__pos__(context=self) return a.__pos__(context=self)
@ -4415,46 +4415,46 @@ class Context(object):
>>> c.Emin = -999 >>> c.Emin = -999
>>> c.Emax = 999 >>> c.Emax = 999
>>> c.power(Decimal('2'), Decimal('3')) >>> c.power(Decimal('2'), Decimal('3'))
Decimal("8") Decimal('8')
>>> c.power(Decimal('-2'), Decimal('3')) >>> c.power(Decimal('-2'), Decimal('3'))
Decimal("-8") Decimal('-8')
>>> c.power(Decimal('2'), Decimal('-3')) >>> c.power(Decimal('2'), Decimal('-3'))
Decimal("0.125") Decimal('0.125')
>>> c.power(Decimal('1.7'), Decimal('8')) >>> c.power(Decimal('1.7'), Decimal('8'))
Decimal("69.7575744") Decimal('69.7575744')
>>> c.power(Decimal('10'), Decimal('0.301029996')) >>> c.power(Decimal('10'), Decimal('0.301029996'))
Decimal("2.00000000") Decimal('2.00000000')
>>> c.power(Decimal('Infinity'), Decimal('-1')) >>> c.power(Decimal('Infinity'), Decimal('-1'))
Decimal("0") Decimal('0')
>>> c.power(Decimal('Infinity'), Decimal('0')) >>> c.power(Decimal('Infinity'), Decimal('0'))
Decimal("1") Decimal('1')
>>> c.power(Decimal('Infinity'), Decimal('1')) >>> c.power(Decimal('Infinity'), Decimal('1'))
Decimal("Infinity") Decimal('Infinity')
>>> c.power(Decimal('-Infinity'), Decimal('-1')) >>> c.power(Decimal('-Infinity'), Decimal('-1'))
Decimal("-0") Decimal('-0')
>>> c.power(Decimal('-Infinity'), Decimal('0')) >>> c.power(Decimal('-Infinity'), Decimal('0'))
Decimal("1") Decimal('1')
>>> c.power(Decimal('-Infinity'), Decimal('1')) >>> c.power(Decimal('-Infinity'), Decimal('1'))
Decimal("-Infinity") Decimal('-Infinity')
>>> c.power(Decimal('-Infinity'), Decimal('2')) >>> c.power(Decimal('-Infinity'), Decimal('2'))
Decimal("Infinity") Decimal('Infinity')
>>> c.power(Decimal('0'), Decimal('0')) >>> c.power(Decimal('0'), Decimal('0'))
Decimal("NaN") Decimal('NaN')
>>> c.power(Decimal('3'), Decimal('7'), Decimal('16')) >>> c.power(Decimal('3'), Decimal('7'), Decimal('16'))
Decimal("11") Decimal('11')
>>> c.power(Decimal('-3'), Decimal('7'), Decimal('16')) >>> c.power(Decimal('-3'), Decimal('7'), Decimal('16'))
Decimal("-11") Decimal('-11')
>>> c.power(Decimal('-3'), Decimal('8'), Decimal('16')) >>> c.power(Decimal('-3'), Decimal('8'), Decimal('16'))
Decimal("1") Decimal('1')
>>> c.power(Decimal('3'), Decimal('7'), Decimal('-16')) >>> c.power(Decimal('3'), Decimal('7'), Decimal('-16'))
Decimal("11") Decimal('11')
>>> c.power(Decimal('23E12345'), Decimal('67E189'), Decimal('123456789')) >>> c.power(Decimal('23E12345'), Decimal('67E189'), Decimal('123456789'))
Decimal("11729830") Decimal('11729830')
>>> c.power(Decimal('-0'), Decimal('17'), Decimal('1729')) >>> c.power(Decimal('-0'), Decimal('17'), Decimal('1729'))
Decimal("-0") Decimal('-0')
>>> c.power(Decimal('-23'), Decimal('0'), Decimal('65537')) >>> c.power(Decimal('-23'), Decimal('0'), Decimal('65537'))
Decimal("1") Decimal('1')
""" """
return a.__pow__(b, modulo, context=self) return a.__pow__(b, modulo, context=self)
@ -4477,35 +4477,35 @@ class Context(object):
if the result is subnormal and inexact. if the result is subnormal and inexact.
>>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.001')) >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.001'))
Decimal("2.170") Decimal('2.170')
>>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.01')) >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.01'))
Decimal("2.17") Decimal('2.17')
>>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.1')) >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.1'))
Decimal("2.2") Decimal('2.2')
>>> ExtendedContext.quantize(Decimal('2.17'), Decimal('1e+0')) >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('1e+0'))
Decimal("2") Decimal('2')
>>> ExtendedContext.quantize(Decimal('2.17'), Decimal('1e+1')) >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('1e+1'))
Decimal("0E+1") Decimal('0E+1')
>>> ExtendedContext.quantize(Decimal('-Inf'), Decimal('Infinity')) >>> ExtendedContext.quantize(Decimal('-Inf'), Decimal('Infinity'))
Decimal("-Infinity") Decimal('-Infinity')
>>> ExtendedContext.quantize(Decimal('2'), Decimal('Infinity')) >>> ExtendedContext.quantize(Decimal('2'), Decimal('Infinity'))
Decimal("NaN") Decimal('NaN')
>>> ExtendedContext.quantize(Decimal('-0.1'), Decimal('1')) >>> ExtendedContext.quantize(Decimal('-0.1'), Decimal('1'))
Decimal("-0") Decimal('-0')
>>> ExtendedContext.quantize(Decimal('-0'), Decimal('1e+5')) >>> ExtendedContext.quantize(Decimal('-0'), Decimal('1e+5'))
Decimal("-0E+5") Decimal('-0E+5')
>>> ExtendedContext.quantize(Decimal('+35236450.6'), Decimal('1e-2')) >>> ExtendedContext.quantize(Decimal('+35236450.6'), Decimal('1e-2'))
Decimal("NaN") Decimal('NaN')
>>> ExtendedContext.quantize(Decimal('-35236450.6'), Decimal('1e-2')) >>> ExtendedContext.quantize(Decimal('-35236450.6'), Decimal('1e-2'))
Decimal("NaN") Decimal('NaN')
>>> ExtendedContext.quantize(Decimal('217'), Decimal('1e-1')) >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e-1'))
Decimal("217.0") Decimal('217.0')
>>> ExtendedContext.quantize(Decimal('217'), Decimal('1e-0')) >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e-0'))
Decimal("217") Decimal('217')
>>> ExtendedContext.quantize(Decimal('217'), Decimal('1e+1')) >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e+1'))
Decimal("2.2E+2") Decimal('2.2E+2')
>>> ExtendedContext.quantize(Decimal('217'), Decimal('1e+2')) >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e+2'))
Decimal("2E+2") Decimal('2E+2')
""" """
return a.quantize(b, context=self) return a.quantize(b, context=self)
@ -4513,7 +4513,7 @@ class Context(object):
"""Just returns 10, as this is Decimal, :) """Just returns 10, as this is Decimal, :)
>>> ExtendedContext.radix() >>> ExtendedContext.radix()
Decimal("10") Decimal('10')
""" """
return Decimal(10) return Decimal(10)
@ -4530,17 +4530,17 @@ class Context(object):
remainder cannot be calculated). remainder cannot be calculated).
>>> ExtendedContext.remainder(Decimal('2.1'), Decimal('3')) >>> ExtendedContext.remainder(Decimal('2.1'), Decimal('3'))
Decimal("2.1") Decimal('2.1')
>>> ExtendedContext.remainder(Decimal('10'), Decimal('3')) >>> ExtendedContext.remainder(Decimal('10'), Decimal('3'))
Decimal("1") Decimal('1')
>>> ExtendedContext.remainder(Decimal('-10'), Decimal('3')) >>> ExtendedContext.remainder(Decimal('-10'), Decimal('3'))
Decimal("-1") Decimal('-1')
>>> ExtendedContext.remainder(Decimal('10.2'), Decimal('1')) >>> ExtendedContext.remainder(Decimal('10.2'), Decimal('1'))
Decimal("0.2") Decimal('0.2')
>>> ExtendedContext.remainder(Decimal('10'), Decimal('0.3')) >>> ExtendedContext.remainder(Decimal('10'), Decimal('0.3'))
Decimal("0.1") Decimal('0.1')
>>> ExtendedContext.remainder(Decimal('3.6'), Decimal('1.3')) >>> ExtendedContext.remainder(Decimal('3.6'), Decimal('1.3'))
Decimal("1.0") Decimal('1.0')
""" """
return a.__mod__(b, context=self) return a.__mod__(b, context=self)
@ -4555,19 +4555,19 @@ class Context(object):
remainder cannot be calculated). remainder cannot be calculated).
>>> ExtendedContext.remainder_near(Decimal('2.1'), Decimal('3')) >>> ExtendedContext.remainder_near(Decimal('2.1'), Decimal('3'))
Decimal("-0.9") Decimal('-0.9')
>>> ExtendedContext.remainder_near(Decimal('10'), Decimal('6')) >>> ExtendedContext.remainder_near(Decimal('10'), Decimal('6'))
Decimal("-2") Decimal('-2')
>>> ExtendedContext.remainder_near(Decimal('10'), Decimal('3')) >>> ExtendedContext.remainder_near(Decimal('10'), Decimal('3'))
Decimal("1") Decimal('1')
>>> ExtendedContext.remainder_near(Decimal('-10'), Decimal('3')) >>> ExtendedContext.remainder_near(Decimal('-10'), Decimal('3'))
Decimal("-1") Decimal('-1')
>>> ExtendedContext.remainder_near(Decimal('10.2'), Decimal('1')) >>> ExtendedContext.remainder_near(Decimal('10.2'), Decimal('1'))
Decimal("0.2") Decimal('0.2')
>>> ExtendedContext.remainder_near(Decimal('10'), Decimal('0.3')) >>> ExtendedContext.remainder_near(Decimal('10'), Decimal('0.3'))
Decimal("0.1") Decimal('0.1')
>>> ExtendedContext.remainder_near(Decimal('3.6'), Decimal('1.3')) >>> ExtendedContext.remainder_near(Decimal('3.6'), Decimal('1.3'))
Decimal("-0.3") Decimal('-0.3')
""" """
return a.remainder_near(b, context=self) return a.remainder_near(b, context=self)
@ -4581,15 +4581,15 @@ class Context(object):
positive or to the right otherwise. positive or to the right otherwise.
>>> ExtendedContext.rotate(Decimal('34'), Decimal('8')) >>> ExtendedContext.rotate(Decimal('34'), Decimal('8'))
Decimal("400000003") Decimal('400000003')
>>> ExtendedContext.rotate(Decimal('12'), Decimal('9')) >>> ExtendedContext.rotate(Decimal('12'), Decimal('9'))
Decimal("12") Decimal('12')
>>> ExtendedContext.rotate(Decimal('123456789'), Decimal('-2')) >>> ExtendedContext.rotate(Decimal('123456789'), Decimal('-2'))
Decimal("891234567") Decimal('891234567')
>>> ExtendedContext.rotate(Decimal('123456789'), Decimal('0')) >>> ExtendedContext.rotate(Decimal('123456789'), Decimal('0'))
Decimal("123456789") Decimal('123456789')
>>> ExtendedContext.rotate(Decimal('123456789'), Decimal('+2')) >>> ExtendedContext.rotate(Decimal('123456789'), Decimal('+2'))
Decimal("345678912") Decimal('345678912')
""" """
return a.rotate(b, context=self) return a.rotate(b, context=self)
@ -4614,11 +4614,11 @@ class Context(object):
"""Returns the first operand after adding the second value its exp. """Returns the first operand after adding the second value its exp.
>>> ExtendedContext.scaleb(Decimal('7.50'), Decimal('-2')) >>> ExtendedContext.scaleb(Decimal('7.50'), Decimal('-2'))
Decimal("0.0750") Decimal('0.0750')
>>> ExtendedContext.scaleb(Decimal('7.50'), Decimal('0')) >>> ExtendedContext.scaleb(Decimal('7.50'), Decimal('0'))
Decimal("7.50") Decimal('7.50')
>>> ExtendedContext.scaleb(Decimal('7.50'), Decimal('3')) >>> ExtendedContext.scaleb(Decimal('7.50'), Decimal('3'))
Decimal("7.50E+3") Decimal('7.50E+3')
""" """
return a.scaleb (b, context=self) return a.scaleb (b, context=self)
@ -4633,15 +4633,15 @@ class Context(object):
coefficient are zeros. coefficient are zeros.
>>> ExtendedContext.shift(Decimal('34'), Decimal('8')) >>> ExtendedContext.shift(Decimal('34'), Decimal('8'))
Decimal("400000000") Decimal('400000000')
>>> ExtendedContext.shift(Decimal('12'), Decimal('9')) >>> ExtendedContext.shift(Decimal('12'), Decimal('9'))
Decimal("0") Decimal('0')
>>> ExtendedContext.shift(Decimal('123456789'), Decimal('-2')) >>> ExtendedContext.shift(Decimal('123456789'), Decimal('-2'))
Decimal("1234567") Decimal('1234567')
>>> ExtendedContext.shift(Decimal('123456789'), Decimal('0')) >>> ExtendedContext.shift(Decimal('123456789'), Decimal('0'))
Decimal("123456789") Decimal('123456789')
>>> ExtendedContext.shift(Decimal('123456789'), Decimal('+2')) >>> ExtendedContext.shift(Decimal('123456789'), Decimal('+2'))
Decimal("345678900") Decimal('345678900')
""" """
return a.shift(b, context=self) return a.shift(b, context=self)
@ -4652,23 +4652,23 @@ class Context(object):
algorithm. algorithm.
>>> ExtendedContext.sqrt(Decimal('0')) >>> ExtendedContext.sqrt(Decimal('0'))
Decimal("0") Decimal('0')
>>> ExtendedContext.sqrt(Decimal('-0')) >>> ExtendedContext.sqrt(Decimal('-0'))
Decimal("-0") Decimal('-0')
>>> ExtendedContext.sqrt(Decimal('0.39')) >>> ExtendedContext.sqrt(Decimal('0.39'))
Decimal("0.624499800") Decimal('0.624499800')
>>> ExtendedContext.sqrt(Decimal('100')) >>> ExtendedContext.sqrt(Decimal('100'))
Decimal("10") Decimal('10')
>>> ExtendedContext.sqrt(Decimal('1')) >>> ExtendedContext.sqrt(Decimal('1'))
Decimal("1") Decimal('1')
>>> ExtendedContext.sqrt(Decimal('1.0')) >>> ExtendedContext.sqrt(Decimal('1.0'))
Decimal("1.0") Decimal('1.0')
>>> ExtendedContext.sqrt(Decimal('1.00')) >>> ExtendedContext.sqrt(Decimal('1.00'))
Decimal("1.0") Decimal('1.0')
>>> ExtendedContext.sqrt(Decimal('7')) >>> ExtendedContext.sqrt(Decimal('7'))
Decimal("2.64575131") Decimal('2.64575131')
>>> ExtendedContext.sqrt(Decimal('10')) >>> ExtendedContext.sqrt(Decimal('10'))
Decimal("3.16227766") Decimal('3.16227766')
>>> ExtendedContext.prec >>> ExtendedContext.prec
9 9
""" """
@ -4678,11 +4678,11 @@ class Context(object):
"""Return the difference between the two operands. """Return the difference between the two operands.
>>> ExtendedContext.subtract(Decimal('1.3'), Decimal('1.07')) >>> ExtendedContext.subtract(Decimal('1.3'), Decimal('1.07'))
Decimal("0.23") Decimal('0.23')
>>> ExtendedContext.subtract(Decimal('1.3'), Decimal('1.30')) >>> ExtendedContext.subtract(Decimal('1.3'), Decimal('1.30'))
Decimal("0.00") Decimal('0.00')
>>> ExtendedContext.subtract(Decimal('1.3'), Decimal('2.07')) >>> ExtendedContext.subtract(Decimal('1.3'), Decimal('2.07'))
Decimal("-0.77") Decimal('-0.77')
""" """
return a.__sub__(b, context=self) return a.__sub__(b, context=self)
@ -4711,21 +4711,21 @@ class Context(object):
context. context.
>>> ExtendedContext.to_integral_exact(Decimal('2.1')) >>> ExtendedContext.to_integral_exact(Decimal('2.1'))
Decimal("2") Decimal('2')
>>> ExtendedContext.to_integral_exact(Decimal('100')) >>> ExtendedContext.to_integral_exact(Decimal('100'))
Decimal("100") Decimal('100')
>>> ExtendedContext.to_integral_exact(Decimal('100.0')) >>> ExtendedContext.to_integral_exact(Decimal('100.0'))
Decimal("100") Decimal('100')
>>> ExtendedContext.to_integral_exact(Decimal('101.5')) >>> ExtendedContext.to_integral_exact(Decimal('101.5'))
Decimal("102") Decimal('102')
>>> ExtendedContext.to_integral_exact(Decimal('-101.5')) >>> ExtendedContext.to_integral_exact(Decimal('-101.5'))
Decimal("-102") Decimal('-102')
>>> ExtendedContext.to_integral_exact(Decimal('10E+5')) >>> ExtendedContext.to_integral_exact(Decimal('10E+5'))
Decimal("1.0E+6") Decimal('1.0E+6')
>>> ExtendedContext.to_integral_exact(Decimal('7.89E+77')) >>> ExtendedContext.to_integral_exact(Decimal('7.89E+77'))
Decimal("7.89E+77") Decimal('7.89E+77')
>>> ExtendedContext.to_integral_exact(Decimal('-Inf')) >>> ExtendedContext.to_integral_exact(Decimal('-Inf'))
Decimal("-Infinity") Decimal('-Infinity')
""" """
return a.to_integral_exact(context=self) return a.to_integral_exact(context=self)
@ -4739,21 +4739,21 @@ class Context(object):
be set. The rounding mode is taken from the context. be set. The rounding mode is taken from the context.
>>> ExtendedContext.to_integral_value(Decimal('2.1')) >>> ExtendedContext.to_integral_value(Decimal('2.1'))
Decimal("2") Decimal('2')
>>> ExtendedContext.to_integral_value(Decimal('100')) >>> ExtendedContext.to_integral_value(Decimal('100'))
Decimal("100") Decimal('100')
>>> ExtendedContext.to_integral_value(Decimal('100.0')) >>> ExtendedContext.to_integral_value(Decimal('100.0'))
Decimal("100") Decimal('100')
>>> ExtendedContext.to_integral_value(Decimal('101.5')) >>> ExtendedContext.to_integral_value(Decimal('101.5'))
Decimal("102") Decimal('102')
>>> ExtendedContext.to_integral_value(Decimal('-101.5')) >>> ExtendedContext.to_integral_value(Decimal('-101.5'))
Decimal("-102") Decimal('-102')
>>> ExtendedContext.to_integral_value(Decimal('10E+5')) >>> ExtendedContext.to_integral_value(Decimal('10E+5'))
Decimal("1.0E+6") Decimal('1.0E+6')
>>> ExtendedContext.to_integral_value(Decimal('7.89E+77')) >>> ExtendedContext.to_integral_value(Decimal('7.89E+77'))
Decimal("7.89E+77") Decimal('7.89E+77')
>>> ExtendedContext.to_integral_value(Decimal('-Inf')) >>> ExtendedContext.to_integral_value(Decimal('-Inf'))
Decimal("-Infinity") Decimal('-Infinity')
""" """
return a.to_integral_value(context=self) return a.to_integral_value(context=self)

View File

@ -62,7 +62,7 @@ class Fraction(numbers.Rational):
""" """
self = super(Fraction, cls).__new__(cls) self = super(Fraction, cls).__new__(cls)
if denominator == 1: if not isinstance(numerator, int) and denominator == 1:
if isinstance(numerator, str): if isinstance(numerator, str):
# Handle construction from strings. # Handle construction from strings.
input = numerator input = numerator
@ -84,24 +84,22 @@ class Fraction(numbers.Rational):
if m.group('sign') == '-': if m.group('sign') == '-':
numerator = -numerator numerator = -numerator
elif (not isinstance(numerator, numbers.Integral) and elif isinstance(numerator, numbers.Rational):
isinstance(numerator, numbers.Rational)): # Handle copies from other rationals. Integrals get
# Handle copies from other rationals. # caught here too, but it doesn't matter because
# denominator is already 1.
other_rational = numerator other_rational = numerator
numerator = other_rational.numerator numerator = other_rational.numerator
denominator = other_rational.denominator denominator = other_rational.denominator
if (not isinstance(numerator, numbers.Integral) or
not isinstance(denominator, numbers.Integral)):
raise TypeError("Fraction(%(numerator)s, %(denominator)s):"
" Both arguments must be integral." % locals())
if denominator == 0: if denominator == 0:
raise ZeroDivisionError('Fraction(%s, 0)' % numerator) raise ZeroDivisionError('Fraction(%s, 0)' % numerator)
numerator = numerator.__index__()
denominator = denominator.__index__()
g = gcd(numerator, denominator) g = gcd(numerator, denominator)
self._numerator = int(numerator // g) self._numerator = numerator // g
self._denominator = int(denominator // g) self._denominator = denominator // g
return self return self
@classmethod @classmethod
@ -138,42 +136,60 @@ class Fraction(numbers.Rational):
else: else:
return cls(digits, 10 ** -exp) return cls(digits, 10 ** -exp)
@classmethod def limit_denominator(self, max_denominator=1000000):
def from_continued_fraction(cls, seq): """Closest Fraction to self with denominator at most max_denominator.
'Build a Fraction from a continued fraction expessed as a sequence'
n, d = 1, 0
for e in reversed(seq):
n, d = d, n
n += e * d
return cls(n, d) if seq else cls(0)
def as_continued_fraction(self): >>> Fraction('3.141592653589793').limit_denominator(10)
'Return continued fraction expressed as a list' Fraction(22, 7)
n = self.numerator >>> Fraction('3.141592653589793').limit_denominator(100)
d = self.denominator Fraction(311, 99)
cf = [] >>> Fraction(1234, 5678).limit_denominator(10000)
while d: Fraction(1234, 5678)
e = int(n // d)
cf.append(e)
n -= e * d
n, d = d, n
return cf
def approximate(self, max_denominator): """
'Best rational approximation with a denominator <= max_denominator' # Algorithm notes: For any real number x, define a *best upper
# XXX First cut at algorithm # approximation* to x to be a rational number p/q such that:
# Still needs rounding rules as specified at #
# http://en.wikipedia.org/wiki/Continued_fraction # (1) p/q >= x, and
if self.denominator <= max_denominator: # (2) if p/q > r/s >= x then s > q, for any rational r/s.
return self #
cf = self.as_continued_fraction() # Define *best lower approximation* similarly. Then it can be
result = Fraction(0) # proved that a rational number is a best upper or lower
for i in range(1, len(cf)): # approximation to x if, and only if, it is a convergent or
new = self.from_continued_fraction(cf[:i]) # semiconvergent of the (unique shortest) continued fraction
if new.denominator > max_denominator: # associated to x.
#
# To find a best rational approximation with denominator <= M,
# we find the best upper and lower approximations with
# denominator <= M and take whichever of these is closer to x.
# In the event of a tie, the bound with smaller denominator is
# chosen. If both denominators are equal (which can happen
# only when max_denominator == 1 and self is midway between
# two integers) the lower bound---i.e., the floor of self, is
# taken.
if max_denominator < 1:
raise ValueError("max_denominator should be at least 1")
if self._denominator <= max_denominator:
return Fraction(self)
p0, q0, p1, q1 = 0, 1, 1, 0
n, d = self._numerator, self._denominator
while True:
a = n//d
q2 = q0+a*q1
if q2 > max_denominator:
break break
result = new p0, q0, p1, q1 = p1, q1, p0+a*p1, q2
return result n, d = d, n-a*d
k = (max_denominator-q0)//q1
bound1 = Fraction(p0+k*p1, q0+k*q1)
bound2 = Fraction(p1, q1)
if abs(bound2 - self) <= abs(bound1-self):
return bound2
else:
return bound1
@property @property
def numerator(a): def numerator(a):
@ -185,14 +201,14 @@ class Fraction(numbers.Rational):
def __repr__(self): def __repr__(self):
"""repr(self)""" """repr(self)"""
return ('Fraction(%r,%r)' % (self.numerator, self.denominator)) return ('Fraction(%r, %r)' % (self._numerator, self._denominator))
def __str__(self): def __str__(self):
"""str(self)""" """str(self)"""
if self.denominator == 1: if self._denominator == 1:
return str(self.numerator) return str(self._numerator)
else: else:
return '%s/%s' % (self.numerator, self.denominator) return '%s/%s' % (self._numerator, self._denominator)
def _operator_fallbacks(monomorphic_operator, fallback_operator): def _operator_fallbacks(monomorphic_operator, fallback_operator):
"""Generates forward and reverse operators given a purely-rational """Generates forward and reverse operators given a purely-rational
@ -360,11 +376,11 @@ class Fraction(numbers.Rational):
if b.denominator == 1: if b.denominator == 1:
power = b.numerator power = b.numerator
if power >= 0: if power >= 0:
return Fraction(a.numerator ** power, return Fraction(a._numerator ** power,
a.denominator ** power) a._denominator ** power)
else: else:
return Fraction(a.denominator ** -power, return Fraction(a._denominator ** -power,
a.numerator ** -power) a._numerator ** -power)
else: else:
# A fractional power will generally produce an # A fractional power will generally produce an
# irrational number. # irrational number.
@ -374,36 +390,36 @@ class Fraction(numbers.Rational):
def __rpow__(b, a): def __rpow__(b, a):
"""a ** b""" """a ** b"""
if b.denominator == 1 and b.numerator >= 0: if b._denominator == 1 and b._numerator >= 0:
# If a is an int, keep it that way if possible. # If a is an int, keep it that way if possible.
return a ** b.numerator return a ** b._numerator
if isinstance(a, numbers.Rational): if isinstance(a, numbers.Rational):
return Fraction(a.numerator, a.denominator) ** b return Fraction(a.numerator, a.denominator) ** b
if b.denominator == 1: if b._denominator == 1:
return a ** b.numerator return a ** b._numerator
return a ** float(b) return a ** float(b)
def __pos__(a): def __pos__(a):
"""+a: Coerces a subclass instance to Fraction""" """+a: Coerces a subclass instance to Fraction"""
return Fraction(a.numerator, a.denominator) return Fraction(a._numerator, a._denominator)
def __neg__(a): def __neg__(a):
"""-a""" """-a"""
return Fraction(-a.numerator, a.denominator) return Fraction(-a._numerator, a._denominator)
def __abs__(a): def __abs__(a):
"""abs(a)""" """abs(a)"""
return Fraction(abs(a.numerator), a.denominator) return Fraction(abs(a._numerator), a._denominator)
def __trunc__(a): def __trunc__(a):
"""trunc(a)""" """trunc(a)"""
if a.numerator < 0: if a._numerator < 0:
return -(-a.numerator // a.denominator) return -(-a._numerator // a._denominator)
else: else:
return a.numerator // a.denominator return a._numerator // a._denominator
def __floor__(a): def __floor__(a):
"""Will be math.floor(a) in 3.0.""" """Will be math.floor(a) in 3.0."""
@ -447,22 +463,22 @@ class Fraction(numbers.Rational):
""" """
# XXX since this method is expensive, consider caching the result # XXX since this method is expensive, consider caching the result
if self.denominator == 1: if self._denominator == 1:
# Get integers right. # Get integers right.
return hash(self.numerator) return hash(self._numerator)
# Expensive check, but definitely correct. # Expensive check, but definitely correct.
if self == float(self): if self == float(self):
return hash(float(self)) return hash(float(self))
else: else:
# Use tuple's hash to avoid a high collision rate on # Use tuple's hash to avoid a high collision rate on
# simple fractions. # simple fractions.
return hash((self.numerator, self.denominator)) return hash((self._numerator, self._denominator))
def __eq__(a, b): def __eq__(a, b):
"""a == b""" """a == b"""
if isinstance(b, numbers.Rational): if isinstance(b, numbers.Rational):
return (a.numerator == b.numerator and return (a._numerator == b.numerator and
a.denominator == b.denominator) a._denominator == b.denominator)
if isinstance(b, numbers.Complex) and b.imag == 0: if isinstance(b, numbers.Complex) and b.imag == 0:
b = b.real b = b.real
if isinstance(b, float): if isinstance(b, float):
@ -517,7 +533,7 @@ class Fraction(numbers.Rational):
def __bool__(a): def __bool__(a):
"""a != 0""" """a != 0"""
return a.numerator != 0 return a._numerator != 0
# support for pickling, copy, and deepcopy # support for pickling, copy, and deepcopy
@ -527,9 +543,9 @@ class Fraction(numbers.Rational):
def __copy__(self): def __copy__(self):
if type(self) == Fraction: if type(self) == Fraction:
return self # I'm immutable; therefore I am my own clone return self # I'm immutable; therefore I am my own clone
return self.__class__(self.numerator, self.denominator) return self.__class__(self._numerator, self._denominator)
def __deepcopy__(self, memo): def __deepcopy__(self, memo):
if type(self) == Fraction: if type(self) == Fraction:
return self # My components are also immutable return self # My components are also immutable
return self.__class__(self.numerator, self.denominator) return self.__class__(self._numerator, self._denominator)

View File

@ -70,6 +70,13 @@ What's New in IDLE 2.6a1?
- Clean up EditorWindow close. - Clean up EditorWindow close.
- Patch 1693258: Fix for duplicate "preferences" menu-OS X. Backport of r56204.
- OSX: Avoid crash for those versions of Tcl/Tk which don't have a console
- Bug in idlelib.MultiCall: Options dialog was crashing IDLE if there was an
option in config-extensions w/o a value. Patch #1672481, Tal Einat
- Corrected some bugs in AutoComplete. Also, Page Up/Down in ACW implemented; - Corrected some bugs in AutoComplete. Also, Page Up/Down in ACW implemented;
mouse and cursor selection in ACWindow implemented; double Tab inserts mouse and cursor selection in ACWindow implemented; double Tab inserts
current selection and closes ACW (similar to double-click and Return); scroll current selection and closes ACW (similar to double-click and Return); scroll

View File

@ -46,9 +46,11 @@ Inexact.register(float)
# Inexact.register(decimal.Decimal) # Inexact.register(decimal.Decimal)
## Notes on Decimal and it how relates to the numeric tower ## Notes on Decimal
## -------------------------------------------------------- ## ----------------
## Decimal is Real except that it does not support rich comparisons. ## Decimal has all of the methods specified by the Real abc, but it should
## not be registered as a Real because decimals do not interoperate with
## binary floats.
## ##
## Decimal has some of the characteristics of Integrals. It provides ## Decimal has some of the characteristics of Integrals. It provides
## logical operations but not as operators. The logical operations only apply ## logical operations but not as operators. The logical operations only apply
@ -304,7 +306,6 @@ class Real(Complex):
return +self return +self
Real.register(float) Real.register(float)
# Real.register(decimal.Decimal)
class Rational(Real, Exact): class Rational(Real, Exact):

View File

@ -81,6 +81,16 @@ class TestABC(unittest.TestCase):
self.assertEqual(issubclass(C, A), True) self.assertEqual(issubclass(C, A), True)
self.assertEqual(isinstance(c, A), True) self.assertEqual(isinstance(c, A), True)
def test_isinstance_invalidation(self):
class A(metaclass=abc.ABCMeta):
pass
class B:
pass
b = B()
self.assertEqual(isinstance(b, A), False)
A.register(B)
self.assertEqual(isinstance(b, A), True)
def test_registration_builtins(self): def test_registration_builtins(self):
class A(metaclass=abc.ABCMeta): class A(metaclass=abc.ABCMeta):
pass pass

View File

@ -1040,7 +1040,7 @@ class DecimalUsabilityTest(unittest.TestCase):
d = Decimal('15.32') d = Decimal('15.32')
self.assertEqual(str(d), '15.32') # str self.assertEqual(str(d), '15.32') # str
self.assertEqual(repr(d), 'Decimal("15.32")') # repr self.assertEqual(repr(d), "Decimal('15.32')") # repr
def test_tonum_methods(self): def test_tonum_methods(self):
#Test float, int and long methods. #Test float, int and long methods.

View File

@ -8,7 +8,7 @@ import fractions
import unittest import unittest
from copy import copy, deepcopy from copy import copy, deepcopy
from pickle import dumps, loads from pickle import dumps, loads
R = fractions.Fraction F = fractions.Fraction
gcd = fractions.gcd gcd = fractions.gcd
@ -49,77 +49,76 @@ class FractionTest(unittest.TestCase):
self.fail("%s not raised" % exc_type.__name__) self.fail("%s not raised" % exc_type.__name__)
def testInit(self): def testInit(self):
self.assertEquals((0, 1), _components(R())) self.assertEquals((0, 1), _components(F()))
self.assertEquals((7, 1), _components(R(7))) self.assertEquals((7, 1), _components(F(7)))
self.assertEquals((7, 3), _components(R(R(7, 3)))) self.assertEquals((7, 3), _components(F(F(7, 3))))
self.assertEquals((-1, 1), _components(R(-1, 1))) self.assertEquals((-1, 1), _components(F(-1, 1)))
self.assertEquals((-1, 1), _components(R(1, -1))) self.assertEquals((-1, 1), _components(F(1, -1)))
self.assertEquals((1, 1), _components(R(-2, -2))) self.assertEquals((1, 1), _components(F(-2, -2)))
self.assertEquals((1, 2), _components(R(5, 10))) self.assertEquals((1, 2), _components(F(5, 10)))
self.assertEquals((7, 15), _components(R(7, 15))) self.assertEquals((7, 15), _components(F(7, 15)))
self.assertEquals((10**23, 1), _components(R(10**23))) self.assertEquals((10**23, 1), _components(F(10**23)))
self.assertRaisesMessage(ZeroDivisionError, "Fraction(12, 0)", self.assertRaisesMessage(ZeroDivisionError, "Fraction(12, 0)",
R, 12, 0) F, 12, 0)
self.assertRaises(TypeError, R, 1.5) self.assertRaises(AttributeError, F, 1.5)
self.assertRaises(TypeError, R, 1.5 + 3j) self.assertRaises(AttributeError, F, 1.5 + 3j)
self.assertRaises(TypeError, R, R(1, 2), 3) self.assertRaises(AttributeError, F, F(1, 2), 3)
self.assertRaises(TypeError, R, "3/2", 3) self.assertRaises(AttributeError, F, "3/2", 3)
def testFromString(self): def testFromString(self):
self.assertEquals((5, 1), _components(R("5"))) self.assertEquals((5, 1), _components(F("5")))
self.assertEquals((3, 2), _components(R("3/2"))) self.assertEquals((3, 2), _components(F("3/2")))
self.assertEquals((3, 2), _components(R(" \n +3/2"))) self.assertEquals((3, 2), _components(F(" \n +3/2")))
self.assertEquals((-3, 2), _components(R("-3/2 "))) self.assertEquals((-3, 2), _components(F("-3/2 ")))
self.assertEquals((3, 2), _components(R(" 03/02 \n "))) self.assertEquals((13, 2), _components(F(" 013/02 \n ")))
self.assertEquals((3, 2), _components(R(" 03/02 \n "))) self.assertEquals((16, 5), _components(F(" 3.2 ")))
self.assertEquals((16, 5), _components(R(" 3.2 "))) self.assertEquals((-16, 5), _components(F(" -3.2 ")))
self.assertEquals((-16, 5), _components(R(" -3.2 "))) self.assertEquals((-3, 1), _components(F(" -3. ")))
self.assertEquals((-3, 1), _components(R(" -3. "))) self.assertEquals((3, 5), _components(F(" .6 ")))
self.assertEquals((3, 5), _components(R(" .6 ")))
self.assertRaisesMessage( self.assertRaisesMessage(
ZeroDivisionError, "Fraction(3, 0)", ZeroDivisionError, "Fraction(3, 0)",
R, "3/0") F, "3/0")
self.assertRaisesMessage( self.assertRaisesMessage(
ValueError, "Invalid literal for Fraction: 3/", ValueError, "Invalid literal for Fraction: 3/",
R, "3/") F, "3/")
self.assertRaisesMessage( self.assertRaisesMessage(
ValueError, "Invalid literal for Fraction: 3 /2", ValueError, "Invalid literal for Fraction: 3 /2",
R, "3 /2") F, "3 /2")
self.assertRaisesMessage( self.assertRaisesMessage(
# Denominators don't need a sign. # Denominators don't need a sign.
ValueError, "Invalid literal for Fraction: 3/+2", ValueError, "Invalid literal for Fraction: 3/+2",
R, "3/+2") F, "3/+2")
self.assertRaisesMessage( self.assertRaisesMessage(
# Imitate float's parsing. # Imitate float's parsing.
ValueError, "Invalid literal for Fraction: + 3/2", ValueError, "Invalid literal for Fraction: + 3/2",
R, "+ 3/2") F, "+ 3/2")
self.assertRaisesMessage( self.assertRaisesMessage(
# Avoid treating '.' as a regex special character. # Avoid treating '.' as a regex special character.
ValueError, "Invalid literal for Fraction: 3a2", ValueError, "Invalid literal for Fraction: 3a2",
R, "3a2") F, "3a2")
self.assertRaisesMessage( self.assertRaisesMessage(
# Only parse ordinary decimals, not scientific form. # Only parse ordinary decimals, not scientific form.
ValueError, "Invalid literal for Fraction: 3.2e4", ValueError, "Invalid literal for Fraction: 3.2e4",
R, "3.2e4") F, "3.2e4")
self.assertRaisesMessage( self.assertRaisesMessage(
# Don't accept combinations of decimals and rationals. # Don't accept combinations of decimals and rationals.
ValueError, "Invalid literal for Fraction: 3/7.2", ValueError, "Invalid literal for Fraction: 3/7.2",
R, "3/7.2") F, "3/7.2")
self.assertRaisesMessage( self.assertRaisesMessage(
# Don't accept combinations of decimals and rationals. # Don't accept combinations of decimals and rationals.
ValueError, "Invalid literal for Fraction: 3.2/7", ValueError, "Invalid literal for Fraction: 3.2/7",
R, "3.2/7") F, "3.2/7")
self.assertRaisesMessage( self.assertRaisesMessage(
# Allow 3. and .3, but not . # Allow 3. and .3, but not .
ValueError, "Invalid literal for Fraction: .", ValueError, "Invalid literal for Fraction: .",
R, ".") F, ".")
def testImmutable(self): def testImmutable(self):
r = R(7, 3) r = F(7, 3)
r.__init__(2, 15) r.__init__(2, 15)
self.assertEquals((7, 3), _components(r)) self.assertEquals((7, 3), _components(r))
@ -132,267 +131,253 @@ class FractionTest(unittest.TestCase):
r._denominator = 2 r._denominator = 2
self.assertEquals((4, 2), _components(r)) self.assertEquals((4, 2), _components(r))
# Which breaks some important operations: # Which breaks some important operations:
self.assertNotEquals(R(4, 2), r) self.assertNotEquals(F(4, 2), r)
def testFromFloat(self): def testFromFloat(self):
self.assertRaisesMessage( self.assertRaisesMessage(
TypeError, "Fraction.from_float() only takes floats, not 3 (int)", TypeError, "Fraction.from_float() only takes floats, not 3 (int)",
R.from_float, 3) F.from_float, 3)
self.assertEquals((0, 1), _components(R.from_float(-0.0))) self.assertEquals((0, 1), _components(F.from_float(-0.0)))
self.assertEquals((10, 1), _components(R.from_float(10.0))) self.assertEquals((10, 1), _components(F.from_float(10.0)))
self.assertEquals((-5, 2), _components(R.from_float(-2.5))) self.assertEquals((-5, 2), _components(F.from_float(-2.5)))
self.assertEquals((99999999999999991611392, 1), self.assertEquals((99999999999999991611392, 1),
_components(R.from_float(1e23))) _components(F.from_float(1e23)))
self.assertEquals(float(10**23), float(R.from_float(1e23))) self.assertEquals(float(10**23), float(F.from_float(1e23)))
self.assertEquals((3602879701896397, 1125899906842624), self.assertEquals((3602879701896397, 1125899906842624),
_components(R.from_float(3.2))) _components(F.from_float(3.2)))
self.assertEquals(3.2, float(R.from_float(3.2))) self.assertEquals(3.2, float(F.from_float(3.2)))
inf = 1e1000 inf = 1e1000
nan = inf - inf nan = inf - inf
self.assertRaisesMessage( self.assertRaisesMessage(
TypeError, "Cannot convert inf to Fraction.", TypeError, "Cannot convert inf to Fraction.",
R.from_float, inf) F.from_float, inf)
self.assertRaisesMessage( self.assertRaisesMessage(
TypeError, "Cannot convert -inf to Fraction.", TypeError, "Cannot convert -inf to Fraction.",
R.from_float, -inf) F.from_float, -inf)
self.assertRaisesMessage( self.assertRaisesMessage(
TypeError, "Cannot convert nan to Fraction.", TypeError, "Cannot convert nan to Fraction.",
R.from_float, nan) F.from_float, nan)
def testFromDecimal(self): def testFromDecimal(self):
self.assertRaisesMessage( self.assertRaisesMessage(
TypeError, TypeError,
"Fraction.from_decimal() only takes Decimals, not 3 (int)", "Fraction.from_decimal() only takes Decimals, not 3 (int)",
R.from_decimal, 3) F.from_decimal, 3)
self.assertEquals(R(0), R.from_decimal(Decimal("-0"))) self.assertEquals(F(0), F.from_decimal(Decimal("-0")))
self.assertEquals(R(5, 10), R.from_decimal(Decimal("0.5"))) self.assertEquals(F(5, 10), F.from_decimal(Decimal("0.5")))
self.assertEquals(R(5, 1000), R.from_decimal(Decimal("5e-3"))) self.assertEquals(F(5, 1000), F.from_decimal(Decimal("5e-3")))
self.assertEquals(R(5000), R.from_decimal(Decimal("5e3"))) self.assertEquals(F(5000), F.from_decimal(Decimal("5e3")))
self.assertEquals(1 - R(1, 10**30), self.assertEquals(1 - F(1, 10**30),
R.from_decimal(Decimal("0." + "9" * 30))) F.from_decimal(Decimal("0." + "9" * 30)))
self.assertRaisesMessage( self.assertRaisesMessage(
TypeError, "Cannot convert Infinity to Fraction.", TypeError, "Cannot convert Infinity to Fraction.",
R.from_decimal, Decimal("inf")) F.from_decimal, Decimal("inf"))
self.assertRaisesMessage( self.assertRaisesMessage(
TypeError, "Cannot convert -Infinity to Fraction.", TypeError, "Cannot convert -Infinity to Fraction.",
R.from_decimal, Decimal("-inf")) F.from_decimal, Decimal("-inf"))
self.assertRaisesMessage( self.assertRaisesMessage(
TypeError, "Cannot convert NaN to Fraction.", TypeError, "Cannot convert NaN to Fraction.",
R.from_decimal, Decimal("nan")) F.from_decimal, Decimal("nan"))
self.assertRaisesMessage( self.assertRaisesMessage(
TypeError, "Cannot convert sNaN to Fraction.", TypeError, "Cannot convert sNaN to Fraction.",
R.from_decimal, Decimal("snan")) F.from_decimal, Decimal("snan"))
def testFromContinuedFraction(self): def testLimitDenominator(self):
self.assertRaises(TypeError, R.from_continued_fraction, None) rpi = F('3.1415926535897932')
phi = R.from_continued_fraction([1]*100) self.assertEqual(rpi.limit_denominator(10000), F(355, 113))
self.assertEquals(round(phi - (1 + 5 ** 0.5) / 2, 10), 0.0) self.assertEqual(-rpi.limit_denominator(10000), F(-355, 113))
self.assertEqual(rpi.limit_denominator(113), F(355, 113))
minusphi = R.from_continued_fraction([-1]*100) self.assertEqual(rpi.limit_denominator(112), F(333, 106))
self.assertEquals(round(minusphi + (1 + 5 ** 0.5) / 2, 10), 0.0) self.assertEqual(F(201, 200).limit_denominator(100), F(1))
self.assertEqual(F(201, 200).limit_denominator(101), F(102, 101))
self.assertEquals(R.from_continued_fraction([0]), R(0)) self.assertEqual(F(0).limit_denominator(10000), F(0))
self.assertEquals(R.from_continued_fraction([]), R(0))
def testAsContinuedFraction(self):
self.assertEqual(R.from_float(math.pi).as_continued_fraction()[:15],
[3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 3, 3])
self.assertEqual(R.from_float(-math.pi).as_continued_fraction()[:16],
[-4, 1, 6, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 3, 3])
self.assertEqual(R(0).as_continued_fraction(), [0])
def testApproximateFrom(self):
self.assertEqual(R.from_float(math.pi).approximate(10000), R(355, 113))
self.assertEqual(R.from_float(-math.pi).approximate(10000), R(-355, 113))
self.assertEqual(R.from_float(0.0).approximate(10000), R(0))
def testConversions(self): def testConversions(self):
self.assertTypedEquals(-1, math.trunc(R(-11, 10))) self.assertTypedEquals(-1, math.trunc(F(-11, 10)))
self.assertTypedEquals(-2, math.floor(R(-11, 10))) self.assertTypedEquals(-2, math.floor(F(-11, 10)))
self.assertTypedEquals(-1, math.ceil(R(-11, 10))) self.assertTypedEquals(-1, math.ceil(F(-11, 10)))
self.assertTypedEquals(-1, math.ceil(R(-10, 10))) self.assertTypedEquals(-1, math.ceil(F(-10, 10)))
self.assertTypedEquals(-1, int(R(-11, 10))) self.assertTypedEquals(-1, int(F(-11, 10)))
self.assertTypedEquals(0, round(F(-1, 10)))
self.assertTypedEquals(0, round(F(-5, 10)))
self.assertTypedEquals(-2, round(F(-15, 10)))
self.assertTypedEquals(-1, round(F(-7, 10)))
self.assertTypedEquals(0, round(R(-1, 10))) self.assertEquals(False, bool(F(0, 1)))
self.assertTypedEquals(0, round(R(-5, 10))) self.assertEquals(True, bool(F(3, 2)))
self.assertTypedEquals(-2, round(R(-15, 10))) self.assertTypedEquals(0.1, float(F(1, 10)))
self.assertTypedEquals(-1, round(R(-7, 10)))
self.assertEquals(False, bool(R(0, 1)))
self.assertEquals(True, bool(R(3, 2)))
self.assertTypedEquals(0.1, float(R(1, 10)))
# Check that __float__ isn't implemented by converting the # Check that __float__ isn't implemented by converting the
# numerator and denominator to float before dividing. # numerator and denominator to float before dividing.
self.assertRaises(OverflowError, float, int('2'*400+'7')) self.assertRaises(OverflowError, float, int('2'*400+'7'))
self.assertAlmostEquals(2.0/3, self.assertAlmostEquals(2.0/3,
float(R(int('2'*400+'7'), int('3'*400+'1')))) float(F(int('2'*400+'7'), int('3'*400+'1'))))
self.assertTypedEquals(0.1+0j, complex(R(1,10))) self.assertTypedEquals(0.1+0j, complex(F(1,10)))
def testRound(self): def testRound(self):
self.assertTypedEquals(R(-200), round(R(-150), -2)) self.assertTypedEquals(F(-200), round(F(-150), -2))
self.assertTypedEquals(R(-200), round(R(-250), -2)) self.assertTypedEquals(F(-200), round(F(-250), -2))
self.assertTypedEquals(R(30), round(R(26), -1)) self.assertTypedEquals(F(30), round(F(26), -1))
self.assertTypedEquals(R(-2, 10), round(R(-15, 100), 1)) self.assertTypedEquals(F(-2, 10), round(F(-15, 100), 1))
self.assertTypedEquals(R(-2, 10), round(R(-25, 100), 1)) self.assertTypedEquals(F(-2, 10), round(F(-25, 100), 1))
def testArithmetic(self): def testArithmetic(self):
self.assertEquals(R(1, 2), R(1, 10) + R(2, 5)) self.assertEquals(F(1, 2), F(1, 10) + F(2, 5))
self.assertEquals(R(-3, 10), R(1, 10) - R(2, 5)) self.assertEquals(F(-3, 10), F(1, 10) - F(2, 5))
self.assertEquals(R(1, 25), R(1, 10) * R(2, 5)) self.assertEquals(F(1, 25), F(1, 10) * F(2, 5))
self.assertEquals(R(1, 4), R(1, 10) / R(2, 5)) self.assertEquals(F(1, 4), F(1, 10) / F(2, 5))
self.assertTypedEquals(2, R(9, 10) // R(2, 5)) self.assertTypedEquals(2, F(9, 10) // F(2, 5))
self.assertTypedEquals(10**23, R(10**23, 1) // R(1)) self.assertTypedEquals(10**23, F(10**23, 1) // F(1))
self.assertEquals(R(2, 3), R(-7, 3) % R(3, 2)) self.assertEquals(F(2, 3), F(-7, 3) % F(3, 2))
self.assertEquals(R(8, 27), R(2, 3) ** R(3)) self.assertEquals(F(8, 27), F(2, 3) ** F(3))
self.assertEquals(R(27, 8), R(2, 3) ** R(-3)) self.assertEquals(F(27, 8), F(2, 3) ** F(-3))
self.assertTypedEquals(2.0, R(4) ** R(1, 2)) self.assertTypedEquals(2.0, F(4) ** F(1, 2))
z = pow(R(-1), R(1, 2)) z = pow(F(-1), F(1, 2))
self.assertAlmostEquals(z.real, 0) self.assertAlmostEquals(z.real, 0)
self.assertEquals(z.imag, 1) self.assertEquals(z.imag, 1)
def testMixedArithmetic(self): def testMixedArithmetic(self):
self.assertTypedEquals(R(11, 10), R(1, 10) + 1) self.assertTypedEquals(F(11, 10), F(1, 10) + 1)
self.assertTypedEquals(1.1, R(1, 10) + 1.0) self.assertTypedEquals(1.1, F(1, 10) + 1.0)
self.assertTypedEquals(1.1 + 0j, R(1, 10) + (1.0 + 0j)) self.assertTypedEquals(1.1 + 0j, F(1, 10) + (1.0 + 0j))
self.assertTypedEquals(R(11, 10), 1 + R(1, 10)) self.assertTypedEquals(F(11, 10), 1 + F(1, 10))
self.assertTypedEquals(1.1, 1.0 + R(1, 10)) self.assertTypedEquals(1.1, 1.0 + F(1, 10))
self.assertTypedEquals(1.1 + 0j, (1.0 + 0j) + R(1, 10)) self.assertTypedEquals(1.1 + 0j, (1.0 + 0j) + F(1, 10))
self.assertTypedEquals(R(-9, 10), R(1, 10) - 1) self.assertTypedEquals(F(-9, 10), F(1, 10) - 1)
self.assertTypedEquals(-0.9, R(1, 10) - 1.0) self.assertTypedEquals(-0.9, F(1, 10) - 1.0)
self.assertTypedEquals(-0.9 + 0j, R(1, 10) - (1.0 + 0j)) self.assertTypedEquals(-0.9 + 0j, F(1, 10) - (1.0 + 0j))
self.assertTypedEquals(R(9, 10), 1 - R(1, 10)) self.assertTypedEquals(F(9, 10), 1 - F(1, 10))
self.assertTypedEquals(0.9, 1.0 - R(1, 10)) self.assertTypedEquals(0.9, 1.0 - F(1, 10))
self.assertTypedEquals(0.9 + 0j, (1.0 + 0j) - R(1, 10)) self.assertTypedEquals(0.9 + 0j, (1.0 + 0j) - F(1, 10))
self.assertTypedEquals(R(1, 10), R(1, 10) * 1) self.assertTypedEquals(F(1, 10), F(1, 10) * 1)
self.assertTypedEquals(0.1, R(1, 10) * 1.0) self.assertTypedEquals(0.1, F(1, 10) * 1.0)
self.assertTypedEquals(0.1 + 0j, R(1, 10) * (1.0 + 0j)) self.assertTypedEquals(0.1 + 0j, F(1, 10) * (1.0 + 0j))
self.assertTypedEquals(R(1, 10), 1 * R(1, 10)) self.assertTypedEquals(F(1, 10), 1 * F(1, 10))
self.assertTypedEquals(0.1, 1.0 * R(1, 10)) self.assertTypedEquals(0.1, 1.0 * F(1, 10))
self.assertTypedEquals(0.1 + 0j, (1.0 + 0j) * R(1, 10)) self.assertTypedEquals(0.1 + 0j, (1.0 + 0j) * F(1, 10))
self.assertTypedEquals(R(1, 10), R(1, 10) / 1) self.assertTypedEquals(F(1, 10), F(1, 10) / 1)
self.assertTypedEquals(0.1, R(1, 10) / 1.0) self.assertTypedEquals(0.1, F(1, 10) / 1.0)
self.assertTypedEquals(0.1 + 0j, R(1, 10) / (1.0 + 0j)) self.assertTypedEquals(0.1 + 0j, F(1, 10) / (1.0 + 0j))
self.assertTypedEquals(R(10, 1), 1 / R(1, 10)) self.assertTypedEquals(F(10, 1), 1 / F(1, 10))
self.assertTypedEquals(10.0, 1.0 / R(1, 10)) self.assertTypedEquals(10.0, 1.0 / F(1, 10))
self.assertTypedEquals(10.0 + 0j, (1.0 + 0j) / R(1, 10)) self.assertTypedEquals(10.0 + 0j, (1.0 + 0j) / F(1, 10))
self.assertTypedEquals(0, R(1, 10) // 1) self.assertTypedEquals(0, F(1, 10) // 1)
self.assertTypedEquals(0, R(1, 10) // 1.0) self.assertTypedEquals(0, F(1, 10) // 1.0)
self.assertTypedEquals(10, 1 // R(1, 10)) self.assertTypedEquals(10, 1 // F(1, 10))
self.assertTypedEquals(10**23, 10**22 // R(1, 10)) self.assertTypedEquals(10**23, 10**22 // F(1, 10))
self.assertTypedEquals(10, 1.0 // R(1, 10)) self.assertTypedEquals(10, 1.0 // F(1, 10))
self.assertTypedEquals(R(1, 10), R(1, 10) % 1) self.assertTypedEquals(F(1, 10), F(1, 10) % 1)
self.assertTypedEquals(0.1, R(1, 10) % 1.0) self.assertTypedEquals(0.1, F(1, 10) % 1.0)
self.assertTypedEquals(R(0, 1), 1 % R(1, 10)) self.assertTypedEquals(F(0, 1), 1 % F(1, 10))
self.assertTypedEquals(0.0, 1.0 % R(1, 10)) self.assertTypedEquals(0.0, 1.0 % F(1, 10))
# No need for divmod since we don't override it. # No need for divmod since we don't override it.
# ** has more interesting conversion rules. # ** has more interesting conversion rules.
self.assertTypedEquals(R(100, 1), R(1, 10) ** -2) self.assertTypedEquals(F(100, 1), F(1, 10) ** -2)
self.assertTypedEquals(R(100, 1), R(10, 1) ** 2) self.assertTypedEquals(F(100, 1), F(10, 1) ** 2)
self.assertTypedEquals(0.1, R(1, 10) ** 1.0) self.assertTypedEquals(0.1, F(1, 10) ** 1.0)
self.assertTypedEquals(0.1 + 0j, R(1, 10) ** (1.0 + 0j)) self.assertTypedEquals(0.1 + 0j, F(1, 10) ** (1.0 + 0j))
self.assertTypedEquals(4 , 2 ** R(2, 1)) self.assertTypedEquals(4 , 2 ** F(2, 1))
z = pow(-1, R(1, 2)) z = pow(-1, F(1, 2))
self.assertAlmostEquals(0, z.real) self.assertAlmostEquals(0, z.real)
self.assertEquals(1, z.imag) self.assertEquals(1, z.imag)
self.assertTypedEquals(R(1, 4) , 2 ** R(-2, 1)) self.assertTypedEquals(F(1, 4) , 2 ** F(-2, 1))
self.assertTypedEquals(2.0 , 4 ** R(1, 2)) self.assertTypedEquals(2.0 , 4 ** F(1, 2))
self.assertTypedEquals(0.25, 2.0 ** R(-2, 1)) self.assertTypedEquals(0.25, 2.0 ** F(-2, 1))
self.assertTypedEquals(1.0 + 0j, (1.0 + 0j) ** R(1, 10)) self.assertTypedEquals(1.0 + 0j, (1.0 + 0j) ** F(1, 10))
def testMixingWithDecimal(self): def testMixingWithDecimal(self):
# Decimal refuses mixed comparisons. # Decimal refuses mixed comparisons.
self.assertRaisesMessage( self.assertRaisesMessage(
TypeError, TypeError,
"unsupported operand type(s) for +: 'Fraction' and 'Decimal'", "unsupported operand type(s) for +: 'Fraction' and 'Decimal'",
operator.add, R(3,11), Decimal('3.1415926')) operator.add, F(3,11), Decimal('3.1415926'))
self.assertNotEquals(R(5, 2), Decimal('2.5')) self.assertNotEquals(F(5, 2), Decimal('2.5'))
def testComparisons(self): def testComparisons(self):
self.assertTrue(R(1, 2) < R(2, 3)) self.assertTrue(F(1, 2) < F(2, 3))
self.assertFalse(R(1, 2) < R(1, 2)) self.assertFalse(F(1, 2) < F(1, 2))
self.assertTrue(R(1, 2) <= R(2, 3)) self.assertTrue(F(1, 2) <= F(2, 3))
self.assertTrue(R(1, 2) <= R(1, 2)) self.assertTrue(F(1, 2) <= F(1, 2))
self.assertFalse(R(2, 3) <= R(1, 2)) self.assertFalse(F(2, 3) <= F(1, 2))
self.assertTrue(R(1, 2) == R(1, 2)) self.assertTrue(F(1, 2) == F(1, 2))
self.assertFalse(R(1, 2) == R(1, 3)) self.assertFalse(F(1, 2) == F(1, 3))
self.assertFalse(R(1, 2) != R(1, 2)) self.assertFalse(F(1, 2) != F(1, 2))
self.assertTrue(R(1, 2) != R(1, 3)) self.assertTrue(F(1, 2) != F(1, 3))
def testMixedLess(self): def testMixedLess(self):
self.assertTrue(2 < R(5, 2)) self.assertTrue(2 < F(5, 2))
self.assertFalse(2 < R(4, 2)) self.assertFalse(2 < F(4, 2))
self.assertTrue(R(5, 2) < 3) self.assertTrue(F(5, 2) < 3)
self.assertFalse(R(4, 2) < 2) self.assertFalse(F(4, 2) < 2)
self.assertTrue(R(1, 2) < 0.6) self.assertTrue(F(1, 2) < 0.6)
self.assertFalse(R(1, 2) < 0.4) self.assertFalse(F(1, 2) < 0.4)
self.assertTrue(0.4 < R(1, 2)) self.assertTrue(0.4 < F(1, 2))
self.assertFalse(0.5 < R(1, 2)) self.assertFalse(0.5 < F(1, 2))
def testMixedLessEqual(self): def testMixedLessEqual(self):
self.assertTrue(0.5 <= R(1, 2)) self.assertTrue(0.5 <= F(1, 2))
self.assertFalse(0.6 <= R(1, 2)) self.assertFalse(0.6 <= F(1, 2))
self.assertTrue(R(1, 2) <= 0.5) self.assertTrue(F(1, 2) <= 0.5)
self.assertFalse(R(1, 2) <= 0.4) self.assertFalse(F(1, 2) <= 0.4)
self.assertTrue(2 <= R(4, 2)) self.assertTrue(2 <= F(4, 2))
self.assertFalse(2 <= R(3, 2)) self.assertFalse(2 <= F(3, 2))
self.assertTrue(R(4, 2) <= 2) self.assertTrue(F(4, 2) <= 2)
self.assertFalse(R(5, 2) <= 2) self.assertFalse(F(5, 2) <= 2)
def testBigFloatComparisons(self): def testBigFloatComparisons(self):
# Because 10**23 can't be represented exactly as a float: # Because 10**23 can't be represented exactly as a float:
self.assertFalse(R(10**23) == float(10**23)) self.assertFalse(F(10**23) == float(10**23))
# The first test demonstrates why these are important. # The first test demonstrates why these are important.
self.assertFalse(1e23 < float(R(math.trunc(1e23) + 1))) self.assertFalse(1e23 < float(F(math.trunc(1e23) + 1)))
self.assertTrue(1e23 < R(math.trunc(1e23) + 1)) self.assertTrue(1e23 < F(math.trunc(1e23) + 1))
self.assertFalse(1e23 <= R(math.trunc(1e23) - 1)) self.assertFalse(1e23 <= F(math.trunc(1e23) - 1))
self.assertTrue(1e23 > R(math.trunc(1e23) - 1)) self.assertTrue(1e23 > F(math.trunc(1e23) - 1))
self.assertFalse(1e23 >= R(math.trunc(1e23) + 1)) self.assertFalse(1e23 >= F(math.trunc(1e23) + 1))
def testBigComplexComparisons(self): def testBigComplexComparisons(self):
self.assertFalse(R(10**23) == complex(10**23)) self.assertFalse(F(10**23) == complex(10**23))
self.assertTrue(R(10**23) > complex(10**23)) self.assertTrue(F(10**23) > complex(10**23))
self.assertFalse(R(10**23) <= complex(10**23)) self.assertFalse(F(10**23) <= complex(10**23))
def testMixedEqual(self): def testMixedEqual(self):
self.assertTrue(0.5 == R(1, 2)) self.assertTrue(0.5 == F(1, 2))
self.assertFalse(0.6 == R(1, 2)) self.assertFalse(0.6 == F(1, 2))
self.assertTrue(R(1, 2) == 0.5) self.assertTrue(F(1, 2) == 0.5)
self.assertFalse(R(1, 2) == 0.4) self.assertFalse(F(1, 2) == 0.4)
self.assertTrue(2 == R(4, 2)) self.assertTrue(2 == F(4, 2))
self.assertFalse(2 == R(3, 2)) self.assertFalse(2 == F(3, 2))
self.assertTrue(R(4, 2) == 2) self.assertTrue(F(4, 2) == 2)
self.assertFalse(R(5, 2) == 2) self.assertFalse(F(5, 2) == 2)
def testStringification(self): def testStringification(self):
self.assertEquals("Fraction(7,3)", repr(R(7, 3))) self.assertEquals("Fraction(7, 3)", repr(F(7, 3)))
self.assertEquals("7/3", str(R(7, 3))) self.assertEquals("7/3", str(F(7, 3)))
self.assertEquals("7", str(R(7, 1))) self.assertEquals("7", str(F(7, 1)))
def testHash(self): def testHash(self):
self.assertEquals(hash(2.5), hash(R(5, 2))) self.assertEquals(hash(2.5), hash(F(5, 2)))
self.assertEquals(hash(10**50), hash(R(10**50))) self.assertEquals(hash(10**50), hash(F(10**50)))
self.assertNotEquals(hash(float(10**23)), hash(R(10**23))) self.assertNotEquals(hash(float(10**23)), hash(F(10**23)))
def testApproximatePi(self): def testApproximatePi(self):
# Algorithm borrowed from # Algorithm borrowed from
# http://docs.python.org/lib/decimal-recipes.html # http://docs.python.org/lib/decimal-recipes.html
three = R(3) three = F(3)
lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24 lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24
while abs(s - lasts) > R(1, 10**9): while abs(s - lasts) > F(1, 10**9):
lasts = s lasts = s
n, na = n+na, na+8 n, na = n+na, na+8
d, da = d+da, da+32 d, da = d+da, da+32
@ -403,9 +388,9 @@ class FractionTest(unittest.TestCase):
def testApproximateCos1(self): def testApproximateCos1(self):
# Algorithm borrowed from # Algorithm borrowed from
# http://docs.python.org/lib/decimal-recipes.html # http://docs.python.org/lib/decimal-recipes.html
x = R(1) x = F(1)
i, lasts, s, fact, num, sign = 0, 0, R(1), 1, 1, 1 i, lasts, s, fact, num, sign = 0, 0, F(1), 1, 1, 1
while abs(s - lasts) > R(1, 10**9): while abs(s - lasts) > F(1, 10**9):
lasts = s lasts = s
i += 2 i += 2
fact *= i * (i-1) fact *= i * (i-1)
@ -415,7 +400,7 @@ class FractionTest(unittest.TestCase):
self.assertAlmostEquals(math.cos(1), s) self.assertAlmostEquals(math.cos(1), s)
def test_copy_deepcopy_pickle(self): def test_copy_deepcopy_pickle(self):
r = R(13, 7) r = F(13, 7)
self.assertEqual(r, loads(dumps(r))) self.assertEqual(r, loads(dumps(r)))
self.assertEqual(id(r), id(copy(r))) self.assertEqual(id(r), id(copy(r)))
self.assertEqual(id(r), id(deepcopy(r))) self.assertEqual(id(r), id(deepcopy(r)))

View File

@ -4546,10 +4546,10 @@ posix_times(PyObject *self, PyObject *noargs)
*/ */
return Py_BuildValue( return Py_BuildValue(
"ddddd", "ddddd",
(double)(kernel.dwHighDateTime*429.4967296 +
kernel.dwLowDateTime*1e-7),
(double)(user.dwHighDateTime*429.4967296 + (double)(user.dwHighDateTime*429.4967296 +
user.dwLowDateTime*1e-7), user.dwLowDateTime*1e-7),
(double)(kernel.dwHighDateTime*429.4967296 +
kernel.dwLowDateTime*1e-7),
(double)0, (double)0,
(double)0, (double)0,
(double)0); (double)0);

4
configure vendored
View File

@ -1,5 +1,5 @@
#! /bin/sh #! /bin/sh
# From configure.in Revision: 60489 . # From configure.in Revision: 60552 .
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.61 for python 3.0. # Generated by GNU Autoconf 2.61 for python 3.0.
# #
@ -1311,7 +1311,7 @@ if test -n "$ac_init_help"; then
Optional Features: Optional Features:
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--enable-universalsdk[SDKDIR] --enable-universalsdk[=SDKDIR]
Build against Mac OS X 10.4u SDK (ppc/i386) Build against Mac OS X 10.4u SDK (ppc/i386)
--enable-framework[=INSTALLDIR] --enable-framework[=INSTALLDIR]
Build (MacOSX|Darwin) framework Build (MacOSX|Darwin) framework

View File

@ -61,7 +61,7 @@ AC_SUBST(CONFIG_ARGS)
CONFIG_ARGS="$ac_configure_args" CONFIG_ARGS="$ac_configure_args"
AC_ARG_ENABLE(universalsdk, AC_ARG_ENABLE(universalsdk,
AC_HELP_STRING(--enable-universalsdk@<:@SDKDIR@:>@, Build against Mac OS X 10.4u SDK (ppc/i386)), AC_HELP_STRING(--enable-universalsdk@<:@=SDKDIR@:>@, Build against Mac OS X 10.4u SDK (ppc/i386)),
[ [
case $enableval in case $enableval in
yes) yes)