Round to specified scale. @param targetScale the target scale @param roundingMode the rounding mode @throws NumericException if target scale is invalid
(int targetScale, RoundingMode roundingMode)
| 1653 | * @throws NumericException if target scale is invalid |
| 1654 | */ |
| 1655 | public void round(int targetScale, RoundingMode roundingMode) { |
| 1656 | if (isNull()) { |
| 1657 | return; |
| 1658 | } |
| 1659 | |
| 1660 | if (targetScale == this.scale) { |
| 1661 | // No rounding needed |
| 1662 | return; |
| 1663 | } |
| 1664 | |
| 1665 | validateScale(targetScale); |
| 1666 | |
| 1667 | if (isZero()) { |
| 1668 | this.scale = targetScale; |
| 1669 | return; |
| 1670 | } |
| 1671 | |
| 1672 | if (this.scale < targetScale) { |
| 1673 | boolean isNegative = isNegative(); |
| 1674 | if (isNegative) { |
| 1675 | negateNonNull(); |
| 1676 | } |
| 1677 | |
| 1678 | // Need to increase scale (add trailing zeros) |
| 1679 | int scaleIncrease = targetScale - this.scale; |
| 1680 | multiplyByPowerOf10InPlace(scaleIncrease); |
| 1681 | this.scale = targetScale; |
| 1682 | |
| 1683 | if (isNegative) { |
| 1684 | negateNonNull(); |
| 1685 | } |
| 1686 | return; |
| 1687 | } |
| 1688 | |
| 1689 | // TODO: optimize the rounding logic by replacing the division by a multiply + shift |
| 1690 | final long hh = this.hh; |
| 1691 | final long hl = this.hl; |
| 1692 | final long lh = this.lh; |
| 1693 | final long ll = this.ll; |
| 1694 | final int scale = this.scale; |
| 1695 | try { |
| 1696 | divide(divider, hh, hl, lh, ll, scale, 0L, 0L, 0L, 1L, 0, this, targetScale, roundingMode); |
| 1697 | } catch (NumericException e) { |
| 1698 | // restore dividend value |
| 1699 | of(hh, hl, lh, ll, scale); |
| 1700 | throw e; |
| 1701 | } |
| 1702 | } |
| 1703 | |
| 1704 | /** |
| 1705 | * Set the scale forcefully without doing any rescaling operations |