Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

decimal.py: logb: round the result if it is greater than prec #51297

Closed
skrah mannequin opened this issue Oct 3, 2009 · 18 comments
Closed

decimal.py: logb: round the result if it is greater than prec #51297

skrah mannequin opened this issue Oct 3, 2009 · 18 comments
Assignees
Labels
stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@skrah
Copy link
Mannequin

skrah mannequin commented Oct 3, 2009

BPO 7048
Nosy @rhettinger, @mdickinson, @skrah
Files
  • logb_additional.decTest
  • decimal_testcases.patch: Update testcases
  • logb.patch
  • scaleb.patch
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/mdickinson'
    closed_at = <Date 2009-12-04.11:10:35.957>
    created_at = <Date 2009-10-03.13:53:16.656>
    labels = ['type-bug', 'library']
    title = 'decimal.py: logb: round the result if it is greater than prec'
    updated_at = <Date 2009-12-04.11:10:35.956>
    user = 'https://github.com/skrah'

    bugs.python.org fields:

    activity = <Date 2009-12-04.11:10:35.956>
    actor = 'mark.dickinson'
    assignee = 'mark.dickinson'
    closed = True
    closed_date = <Date 2009-12-04.11:10:35.957>
    closer = 'mark.dickinson'
    components = ['Library (Lib)']
    creation = <Date 2009-10-03.13:53:16.656>
    creator = 'skrah'
    dependencies = []
    files = ['15067', '15070', '15071', '15411']
    hgrepos = []
    issue_num = 7048
    keywords = ['patch']
    message_count = 18.0
    messages = ['93492', '93500', '93686', '93687', '93703', '93704', '93705', '93706', '93707', '93715', '93718', '93749', '94277', '94278', '94563', '94565', '95788', '95960']
    nosy_count = 3.0
    nosy_names = ['rhettinger', 'mark.dickinson', 'skrah']
    pr_nums = []
    priority = 'normal'
    resolution = 'fixed'
    stage = 'test needed'
    status = 'closed'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue7048'
    versions = ['Python 2.6', 'Python 3.1', 'Python 2.7', 'Python 3.2']

    @skrah
    Copy link
    Mannequin Author

    skrah mannequin commented Oct 3, 2009

    >>> from decimal import *
    >>> c = getcontext()
    >>> c.prec = 2
    >>> c.logb(Decimal("1E123456"))
    Decimal('123456')
    >>> 

    This result agrees with the result of decNumber, but the spec says:
    "All results are exact unless an integer result does not fit in the
    available precision."

    My interpretation is that the result should be 1.2E+5.

    @mdickinson
    Copy link
    Member

    Hmm. The problem here is that the specification says nothing at all
    about what should happen if the integer result does *not* fit in the
    available precision, so in this case we went with the decNumber
    behaviour.

    Rather than rounding, I'd say that a more useful result in this case
    would be to signal InvalidOperation, on the basis that an inexact result
    from logb is likely to invalidate most uses of it.

    Maybe we should ask Mike Cowlishaw what the intended behaviour here is?

    IEEE 754-2008 (section 5.3.3) requires that languages define a
    'logBFormat' type that's always big enough to hold the logB result. If
    the result is a Decimal, one way to ensure this would be to place
    constraints on the allowable values emax and emin for a given precision.

    @mdickinson
    Copy link
    Member

    (Stefan emailed Mike Cowlishaw about this: thanks, Stefan!)

    Mike's initial response suggests that we *should* be rounding the result
    here. That is, decNumber and decimal.py are both in error, and Stefan's
    interpretation is correct.

    @mdickinson mdickinson added the stdlib Python modules in the Lib dir label Oct 7, 2009
    @mdickinson mdickinson self-assigned this Oct 7, 2009
    @mdickinson mdickinson added the type-bug An unexpected behavior, bug, or error label Oct 7, 2009
    @mdickinson
    Copy link
    Member

    Attaching additional testcases from Mike Cowlishaw.

    @rhettinger
    Copy link
    Contributor

    Mike's response makes sense to me. If the precision is 2, the result
    should round to that precision. The documents showing the theory behind
    the decimal spec indicate that in general mathematical operations are
    exact, only the results get rounded. Also IIRC, the use of
    InvalidOperation is limited to the mathematical part, not the rounding step.

    @mdickinson
    Copy link
    Member

    Patch to update to the most recent official set of tests.

    With this patch, logb and scaleb fail.

    @mdickinson
    Copy link
    Member

    Patch to fix logb.

    @mdickinson
    Copy link
    Member

    I don't understand the new scaleb testcases (from Mike). They look like
    this:

    precision: 34
    maxExponent: 999999999
    minExponent: -999999999
    -- integer overflow in 3.61 or earlier
    scbx164 scaleb 1E-999999999 -1200000000 -> NaN Invalid_operation
    -- out of range
    scbx165 scaleb -1E-999999999 +1200000000 -> NaN Invalid_operation

    The specification says that the second operand should be in the range
    +/-2*(Emax+precision) inclusive, which in this case it is. So clearly
    there are additional situations in which Invalid_operation should be
    signalled. It's not clear to me what those conditions are.

    @mdickinson
    Copy link
    Member

    The IEEE 754-2008 description of scaleB makes a lot more sense, IMO:
    scaleB(x, N) is simply x*10**N (assuming that B=10 and N is integral),
    rounded in the usual way.

    The restriction in the specification seems arbitrary and questionable.
    Presumably it's intended to aid implementation in low-level languages.

    @mdickinson
    Copy link
    Member

    Applied the fix for logb in r75275 (trunk), r75276 (py3k) and r75277
    (release31-maint). r75275 still needs to be merged to the release26-maint
    branch once it's unfrozen.

    @skrah
    Copy link
    Mannequin Author

    skrah mannequin commented Oct 7, 2009

    precision: 34
    maxExponent: 999999999
    minExponent: -999999999
    -- integer overflow in 3.61 or earlier
    scbx164 scaleb 1E-999999999 -1200000000 -> NaN Invalid_operation
    -- out of range
    scbx165 scaleb -1E-999999999 +1200000000 -> NaN Invalid_operation

    I would say that this is implementation specific, as a workaround for
    the overflow. This isn't in the spec at the moment.

    @mdickinson
    Copy link
    Member

    I've updated to the newest version of the test-suite in r75285 through
    r75287. As before, r75285 needs to be backported to the 2.6 maintenance
    branch once its unfrozen.

    I'm currently skipping those two scaleb tests, until we work out what
    should be going on here.

    @mdickinson
    Copy link
    Member

    I just want to note another problem with logb: it doesn't use the correct
    context when processing NaNs. This needs a test and a fix.

    @mdickinson
    Copy link
    Member

    Sorry; ignore that last. I was confused by the fact that the _check_nans
    call came before the 'if context is None' test. But _check_nans deals
    correctly with a context of None, so logb is fine.

    @mdickinson
    Copy link
    Member

    logb fix applied to release26-maint in r75804.

    @mdickinson
    Copy link
    Member

    Updated release26-maint to new test-suite in r75806.

    @mdickinson
    Copy link
    Member

    There's a restriction on the second argument to scaleb in the spec,
    namely that scaleb should be in the range -2*(Emax + precision) to
    2*(Emax + precision) inclusive.

    This restriction seems entirely arbitrary and unnecessary to me. My
    guess is that it's there to ease implementation in low-level languages,
    but it makes little sense for the Python implementation.

    Here's a patch that removes this restriction on scaleb in the Python
    implementation, and skips the corresponding tests.

    @mdickinson
    Copy link
    Member

    Mike Cowlishaw has confirmed that the tests scbx164, scbx165 (in version
    2.59 of the tests) are implementation-specific, so test_decimal is doing
    the right thing in skipping them. So I think this issue can be closed.

    I don't think it's worth removing the restriction on the 2nd scaleb
    argument: while I still think it's arbitrary and unnecessary, keeping it
    allows us to say that we're in full compliance with the specification.

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
    Projects
    None yet
    Development

    No branches or pull requests

    2 participants