Divide and Get Remainder at the same time?

后端 未结 9 1123
不知归路
不知归路 2020-12-15 02:37

Apparently, x86 (and probably a lot of other instruction sets) put both the quotient and the remainder of a divide operation in separate registers.

Now, we can proba

相关标签:
9条回答
  • 2020-12-15 03:17

    Common Lisp does: http://www.lispworks.com/documentation/HyperSpec/Body/f_floorc.htm

    0 讨论(0)
  • 2020-12-15 03:20

    C has div and ldiv. Whether these generate separate instructions for the quotient and remainder will depend on your particular standard library implementation and compiler and optimization settings. Starting with C99, you also have lldiv for larger numbers.

    0 讨论(0)
  • 2020-12-15 03:21

    Python does.

    >>> divmod(9, 4)
    (2, 1)
    

    Which is odd, becuase Python is such a high level language.

    So does Ruby:

    11.divmod(3) #=> [3, 2]
    

    * EDIT *

    It should be noted that the purpose of these operators is probably not to do the work as efficiently as possible, it is more likely the functions exist for correctness/portability reasons.

    For those interested, I believe this is the code of the Python implementation for integer divmod:

    static enum divmod_result
    i_divmod(register long x, register long y,
         long *p_xdivy, long *p_xmody)
    {
    long xdivy, xmody;
    
    if (y == 0) {
        PyErr_SetString(PyExc_ZeroDivisionError,
                        "integer division or modulo by zero");
        return DIVMOD_ERROR;
    }
    /* (-sys.maxint-1)/-1 is the only overflow case. */
    if (y == -1 && UNARY_NEG_WOULD_OVERFLOW(x))
        return DIVMOD_OVERFLOW;
    xdivy = x / y;
    /* xdiv*y can overflow on platforms where x/y gives floor(x/y)
     * for x and y with differing signs. (This is unusual
     * behaviour, and C99 prohibits it, but it's allowed by C89;
     * for an example of overflow, take x = LONG_MIN, y = 5 or x =
     * LONG_MAX, y = -5.)  However, x - xdivy*y is always
     * representable as a long, since it lies strictly between
     * -abs(y) and abs(y).  We add casts to avoid intermediate
     * overflow.
     */
    xmody = (long)(x - (unsigned long)xdivy * y);
    /* If the signs of x and y differ, and the remainder is non-0,
     * C89 doesn't define whether xdivy is now the floor or the
     * ceiling of the infinitely precise quotient.  We want the floor,
     * and we have it iff the remainder's sign matches y's.
     */
    if (xmody && ((y ^ xmody) < 0) /* i.e. and signs differ */) {
        xmody += y;
        --xdivy;
        assert(xmody && ((y ^ xmody) >= 0));
    }
    *p_xdivy = xdivy;
    *p_xmody = xmody;
    return DIVMOD_OK;
    }
    
    0 讨论(0)
提交回复
热议问题