floorMod 与 floorDiv
大约 2 分钟
floorMod 与 floorDiv
Python 翻译 Java 经典错误:
取模/余
print(4 % -3) # -2
print(-4 % 3) # 2
System.out.println(4 % -3); // 1
System.out.println(-4 % 3); // -1
System.out.println(Math.floorMod(4, -3)); // -2
System.out.println(Math.floorMod(-4, 3)); // 2
除法
print(-4 // 3) # -2
System.out.println(-4 / 3); // -1
System.out.println(Math.floorDiv(-4, 3)); // -2
floorMod
/**
* Returns the floor modulus of the {@code int} arguments.
* <p>
* The floor modulus is {@code x - (floorDiv(x, y) * y)},
* has the same sign as the divisor {@code y}, and
* is in the range of {@code -abs(y) < r < +abs(y)}.
*
* <p>
* The relationship between {@code floorDiv} and {@code floorMod} is such that:
* <ul>
* <li>{@code floorDiv(x, y) * y + floorMod(x, y) == x}
* </ul>
* <p>
* The difference in values between {@code floorMod} and
* the {@code %} operator is due to the difference between
* {@code floorDiv} that returns the integer less than or equal to the quotient
* and the {@code /} operator that returns the integer closest to zero.
* <p>
* Examples:
* <ul>
* <li>If the signs of the arguments are the same, the results
* of {@code floorMod} and the {@code %} operator are the same.<br>
* <ul>
* <li>{@code floorMod(+4, +3) == +1}; and {@code (+4 % +3) == +1}</li>
* <li>{@code floorMod(-4, -3) == -1}; and {@code (-4 % -3) == -1}</li>
* </ul>
* <li>If the signs of the arguments are different, the results
* differ from the {@code %} operator.<br>
* <ul>
* <li>{@code floorMod(+4, -3) == -2}; and {@code (+4 % -3) == +1}</li>
* <li>{@code floorMod(-4, +3) == +2}; and {@code (-4 % +3) == -1}</li>
* </ul>
* </li>
* </ul>
* <p>
* If the signs of arguments are unknown and a positive modulus
* is needed it can be computed as {@code (floorMod(x, y) + abs(y)) % abs(y)}.
*
* @param x the dividend
* @param y the divisor
* @return the floor modulus {@code x - (floorDiv(x, y) * y)}
* @throws ArithmeticException if the divisor {@code y} is zero
* @see #floorDiv(int, int)
* @since 1.8
*/
public static int floorMod(int x, int y) {
int mod = x % y;
// if the signs are different and modulo not zero, adjust result
if ((mod ^ y) < 0 && mod != 0) {
mod += y;
}
return mod;
}
floorDiv
/**
* Returns the largest (closest to positive infinity)
* {@code int} value that is less than or equal to the algebraic quotient.
* There is one special case, if the dividend is the
* {@linkplain Integer#MIN_VALUE Integer.MIN_VALUE} and the divisor is {@code -1},
* then integer overflow occurs and
* the result is equal to {@code Integer.MIN_VALUE}.
* <p>
* Normal integer division operates under the round to zero rounding mode
* (truncation). This operation instead acts under the round toward
* negative infinity (floor) rounding mode.
* The floor rounding mode gives different results from truncation
* when the exact result is negative.
* <ul>
* <li>If the signs of the arguments are the same, the results of
* {@code floorDiv} and the {@code /} operator are the same. <br>
* For example, {@code floorDiv(4, 3) == 1} and {@code (4 / 3) == 1}.</li>
* <li>If the signs of the arguments are different, the quotient is negative and
* {@code floorDiv} returns the integer less than or equal to the quotient
* and the {@code /} operator returns the integer closest to zero.<br>
* For example, {@code floorDiv(-4, 3) == -2},
* whereas {@code (-4 / 3) == -1}.
* </li>
* </ul>
*
* @param x the dividend
* @param y the divisor
* @return the largest (closest to positive infinity)
* {@code int} value that is less than or equal to the algebraic quotient.
* @throws ArithmeticException if the divisor {@code y} is zero
* @see #floorMod(int, int)
* @see #floor(double)
* @since 1.8
*/
public static int floorDiv(int x, int y) {
int r = x / y;
// if the signs are different and modulo not zero, round down
if ((x ^ y) < 0 && (r * y != x)) {
r--;
}
return r;
}
(全文完)