Message 335867 - Python tracker

Message335867

Author rhettinger
Recipients Au Vo, mark.dickinson, remi.lapeyre, rhettinger, skrah, tim.peters
Date 2019-02-18.21:01:16
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1550523676.99.0.815466235305.issue36028@roundup.psfhosted.org>
In-reply-to
Content
I'm thinking this due to having two different algorithms in play, one of which has multiple intermediate roundings.

* For starters, 0.4 is not exactly representable. It is stored as the binary fraction 3602879701896397 / 9007199254740992 represented in hex as 0x1.999999999999ap-2

* The / true division operator is implemented in Objects/floatobject.c:float_div() with a single, straight division of C doubles: "a = a / b;"  That is giving 10.0 when rounded.

* The // floor division operator is implemented in Objects/floatobject.c:float_floor_div() which in turn calls float_divmod().  The latter has a number of steps that can each have a round-off and can make adjustments to preserve sign logic invariants:

    mod = fmod(vx, wx);
    /* fmod is typically exact, so vx-mod is *mathematically* an
       exact multiple of wx.  But this is fp arithmetic, and fp
       vx - mod is an approximation; the result is that div may
       not be an exact integral value after the division, although
       it will always be very close to one.
    */
    div = (vx - mod) / wx;
    if (mod) {
        /* ensure the remainder has the same sign as the denominator */
        if ((wx < 0) != (mod < 0)) {
            mod += wx;
            div -= 1.0;
        }
    }
    else {
        /* the remainder is zero, and in the presence of signed zeroes
           fmod returns different results across platforms; ensure
           it has the same sign as the denominator. */
        mod = copysign(0.0, wx);
    }
    /* snap quotient to nearest integral value */
    if (div) {
        floordiv = floor(div);
        if (div - floordiv > 0.5)
            floordiv += 1.0;
    }
    else {
        /* div is zero - get the same sign as the true quotient */
        floordiv = copysign(0.0, vx / wx); /* zero w/ sign of vx/wx */
    }

I don't see how to fix the discrepancy without having float_div() depend on the much slower logic in float_divmod().
History
Date User Action Args
2019-02-18 21:01:17rhettingersetrecipients: + rhettinger, tim.peters, mark.dickinson, skrah, remi.lapeyre, Au Vo
2019-02-18 21:01:16rhettingersetmessageid: <1550523676.99.0.815466235305.issue36028@roundup.psfhosted.org>
2019-02-18 21:01:16rhettingerlinkissue36028 messages
2019-02-18 21:01:16rhettingercreate