Bugs item #1725899, was opened at 2007-05-25 19:52 Message generated for change (Comment added) made by facundobatista You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1725899&group_id=5470
Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: Python Library Group: Python 2.5 >Status: Closed >Resolution: Fixed Priority: 5 Private: No Submitted By: Mark Dickinson (marketdickinson) Assigned to: Facundo Batista (facundobatista) Summary: decimal sqrt method doesn't use round-half-even Initial Comment: According to version 1.66 of Cowlishaw's `General Decimal Arithmetic Specification' the square-root operation in the decimal module should round using the round-half-even algorithm (regardless of the rounding setting in the current context). It doesn't appear to do so: >>> from decimal import * >>> getcontext().prec = 6 >>> Decimal(9123455**2).sqrt() Decimal("9.12345E+6") The exact value of this square root is exactly halfway between two representable Decimals, so using round-half-even with 6 digits I'd expect the answer to be rounded to the neighboring representable Decimal with *even* last digit---that is, Decimal("9.12346E+6") This bug only seems to occur when the number of significant digits in the argument exceeds the current precision (indeed, if the number of sig. digits in the argument is less than or equal to the current precision then it's impossible for the square root to be halfway between two representable floats). It seems to me that this is a minor bug that will occur rarely and is unlikely to have any serious effect even when it does occur; however, it does seem to be a deviation from the specification. ---------------------------------------------------------------------- >Comment By: Facundo Batista (facundobatista) Date: 2007-08-02 00:15 Message: Logged In: YES user_id=752496 Originator: NO Fixed in the revisions 56654 to 56656, in the decimal-branch, using patches generated by Mark, thanks! ---------------------------------------------------------------------- Comment By: Mark Dickinson (marketdickinson) Date: 2007-06-22 15:57 Message: Logged In: YES user_id=703403 Originator: YES See patch 1741308. I'll contact Mike Cowlishaw to verify that the reference implementation really is buggy. ---------------------------------------------------------------------- Comment By: Tim Peters (tim_one) Date: 2007-06-22 13:06 Message: Logged In: YES user_id=31435 Originator: NO Of course you're right, the spec does say inputs shouldn't be rounded. And that last example is horrendous: sqrt should definitely be monotonic (a floating function f is "monotonic" if it guarantees f(x) >= f(y) whenever x >= y; you found x and y such that x > y but sqrt(x) < sqrt(y) -- ouch!). ---------------------------------------------------------------------- Comment By: Mark Dickinson (marketdickinson) Date: 2007-06-22 03:35 Message: Logged In: YES user_id=703403 Originator: YES One more result. This is definitely getting suspicious now--I'll submit my patch. >>> from decimal import * >>> getcontext().prec = 3 >>> Decimal(11772).sqrt() Decimal("109") >>> Decimal(11774).sqrt() Decimal("108") ---------------------------------------------------------------------- Comment By: Mark Dickinson (marketdickinson) Date: 2007-06-22 03:16 Message: Logged In: YES user_id=703403 Originator: YES Some more strange results for sqrt(): with Emax = 9, Emin = -9 and prec = 3: 1. In the following, should the Subnormal and Underflow flags be set? The result before rounding is subnormal, even though the post-rounding result is not, and the spec seems to say that those flags should be set in this situation. But Cowlishaw's reference implementation (version 3.50) doesn't set these flags. (If 9.998 is replaced by 9.99 then the flags *are* set, which seems inconsistent.) >>> Decimal("9.998E-19").sqrt() Decimal("1.00E-9") >>> getcontext() Context(prec=3, rounding=ROUND_HALF_EVEN, Emin=-9, Emax=9, capitals=1, flags=[Rounded, Inexact], traps=[DivisionByZero, Overflow, InvalidOperation]) 2. As I understand the spec, the following result is incorrect: >>> Decimal("1.12E-19").sqrt() Decimal("3.4E-10") (The true value of the square root is 3.34664...e-10, which should surely be rounded to 3.3E-10, not 3.4E-10?). But again, Cowlishaw's reference implementation also gives 3.4E-10. 3. Similarly for the following >>> Decimal("4.21E-20").sqrt() Decimal("2.0E-10") The answer should, I think, be 2.1E-10; here the reference implementation also gives 2.1E-10. 4. And I can't justify this one at all... >>> Decimal("1.01001").sqrt() Decimal("1.01") Shouldn't this be 1.00? But again Python agrees with the reference implementation. Either all this is pretty mixed up, or I'm fundamentally misunderstanding things. I have a patch that I think fixes all these bugs; if there's any agreement that they really are bugs then I'll post it. Can anyone shed any light on the above results? ---------------------------------------------------------------------- Comment By: Mark Dickinson (marketdickinson) Date: 2007-05-25 20:30 Message: Logged In: YES user_id=703403 Originator: YES I don't think inputs should be rounded; note 1 near the start of the `Arithmetic Operations' section of the specification says: "Operands may have more than precision digits and are not rounded before use." ---------------------------------------------------------------------- Comment By: Tim Peters (tim_one) Date: 2007-05-25 20:24 Message: Logged In: YES user_id=31435 Originator: NO Doesn't the spec also require that /inputs/ get rounded to working precision /before/ operations are performed? If so, the exact square 83237431137025 is rounded down to 83237400000000, and sqrt(83237400000000) is 9.12345E+6 rounded to 6 digits. ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1725899&group_id=5470 _______________________________________________ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com