Java: How do I perform integer division that rounds towards -Infinity rather than 0?

前端 未结 4 1524
轮回少年
轮回少年 2020-12-17 16:20

(note: not the same as this other question since the OP never explicitly specified rounding towards 0 or -Infinity)

JLS 15.17.2 says that integer di

4条回答
  •  失恋的感觉
    2020-12-17 17:07

    There's a rather neat formula for this that works when n < 0 and d > 0: take the bitwise complement of n, do the division, and then take the bitwise complement of the result.

    int ifloordiv(int n, int d)
    {
        if (n >= 0)
            return n / d;
        else
            return ~(~n / d);
    }
    

    For the remainder, a similar construction works (compatible with ifloordiv in the sense that the usual invariant ifloordiv(n, d) * d + ifloormod(n, d) == n is satisfied) giving a result that's always in the range [0, d).

    int ifloormod(int n, int d)
    {
        if (n >= 0)
            return n % d;
        else
            return d + ~(~n % d);
    }
    

    For negative divisors, the formulas aren't quite so neat. Here are expanded versions of ifloordiv and ifloormod that follow your 'nice-to-have' behavior option (b) for negative divisors.

    int ifloordiv(int n, int d)
    {
        if (d >= 0)
            return n >= 0 ? n / d : ~(~n / d);
        else
            return n <= 0 ? n / d : (n - 1) / d - 1;
    }
    
    int ifloormod(int n, int d)
    {
        if (d >= 0)
            return n >= 0 ? n % d : d + ~(~n % d);
        else
            return n <= 0 ? n % d : d + 1 + (n - 1) % d;
    }
    

    For d < 0, there's an unavoidable problem case when d == -1 and n is Integer.MIN_VALUE, since then the mathematical result overflows the type. In that case, the formula above returns the wrapped result, just as the usual Java division does. As far as I'm aware, this is the only corner case where we silently get 'wrong' results.

提交回复
热议问题