Returns the result of dividing p by q, rounding using the specified RoundingMode. @throws ArithmeticException if q == 0, or if mode == UNNECESSARY and a is not an integer multiple of b
(int p, int q, RoundingMode mode)
| 326 | */ |
| 327 | |
| 328 | @SuppressWarnings("fallthrough") |
| 329 | public static int divide(int p, int q, RoundingMode mode) { |
| 330 | checkNotNull(mode); |
| 331 | if (q == 0) { |
| 332 | throw new ArithmeticException("/ by zero"); // for GWT |
| 333 | } |
| 334 | |
| 335 | int div = p / q; |
| 336 | int rem = p - q * div; // equal to p % q |
| 337 | if (rem == 0) { |
| 338 | return div; |
| 339 | } |
| 340 | |
| 341 | /* |
| 342 | * Normal Java division rounds towards 0, consistently with RoundingMode.DOWN. We just have to |
| 343 | * deal with the cases where rounding towards 0 is wrong, which typically depends on the sign of |
| 344 | * p / q. |
| 345 | * |
| 346 | * signum is 1 if p and q are both nonnegative or both negative, and -1 otherwise. |
| 347 | */ |
| 348 | |
| 349 | int signum = 1 | ((p ^ q) >> (Integer.SIZE - 1)); |
| 350 | boolean increment; |
| 351 | switch (mode) { |
| 352 | case UNNECESSARY: |
| 353 | checkRoundingUnnecessary(rem == 0); |
| 354 | // fall through |
| 355 | case DOWN: |
| 356 | increment = false; |
| 357 | break; |
| 358 | case UP: |
| 359 | increment = true; |
| 360 | break; |
| 361 | case CEILING: |
| 362 | increment = signum > 0; |
| 363 | break; |
| 364 | case FLOOR: |
| 365 | increment = signum < 0; |
| 366 | break; |
| 367 | case HALF_EVEN: |
| 368 | case HALF_DOWN: |
| 369 | case HALF_UP: |
| 370 | int absRem = abs(rem); |
| 371 | int cmpRemToHalfDivisor = absRem - (abs(q) - absRem); |
| 372 | // subtracting two nonnegative ints can't overflow |
| 373 | // cmpRemToHalfDivisor has the same sign as compare(abs(rem), abs(q) / 2). |
| 374 | if (cmpRemToHalfDivisor == 0) { // exactly on the half mark |
| 375 | increment = (mode == HALF_UP || (mode == HALF_EVEN & (div & 1) != 0)); |
| 376 | } else { |
| 377 | increment = cmpRemToHalfDivisor > 0; // closer to the UP value |
| 378 | } |
| 379 | break; |
| 380 | default: |
| 381 | throw new AssertionError(); |
| 382 | } |
| 383 | return increment? div + signum : div; |
| 384 | } |
| 385 |
no test coverage detected