1 /* 2 * Copyright (C) 2020 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14 15 package com.google.common.math; 16 17 import com.google.common.annotations.GwtIncompatible; 18 import java.math.BigDecimal; 19 import java.math.RoundingMode; 20 21 /** 22 * A class for arithmetic on {@link BigDecimal} that is not covered by its built-in methods. 23 * 24 * @author Louis Wasserman 25 * @since 30.0 26 */ 27 @GwtIncompatible 28 @ElementTypesAreNonnullByDefault 29 public class BigDecimalMath { BigDecimalMath()30 private BigDecimalMath() {} 31 32 /** 33 * Returns {@code x}, rounded to a {@code double} with the specified rounding mode. If {@code x} 34 * is precisely representable as a {@code double}, its {@code double} value will be returned; 35 * otherwise, the rounding will choose between the two nearest representable values with {@code 36 * mode}. 37 * 38 * <p>For the case of {@link RoundingMode#HALF_DOWN}, {@code HALF_UP}, and {@code HALF_EVEN}, 39 * infinite {@code double} values are considered infinitely far away. For example, 2^2000 is not 40 * representable as a double, but {@code roundToDouble(BigDecimal.valueOf(2).pow(2000), HALF_UP)} 41 * will return {@code Double.MAX_VALUE}, not {@code Double.POSITIVE_INFINITY}. 42 * 43 * <p>For the case of {@link RoundingMode#HALF_EVEN}, this implementation uses the IEEE 754 44 * default rounding mode: if the two nearest representable values are equally near, the one with 45 * the least significant bit zero is chosen. (In such cases, both of the nearest representable 46 * values are even integers; this method returns the one that is a multiple of a greater power of 47 * two.) 48 * 49 * @throws ArithmeticException if {@code mode} is {@link RoundingMode#UNNECESSARY} and {@code x} 50 * is not precisely representable as a {@code double} 51 * @since 30.0 52 */ roundToDouble(BigDecimal x, RoundingMode mode)53 public static double roundToDouble(BigDecimal x, RoundingMode mode) { 54 return BigDecimalToDoubleRounder.INSTANCE.roundToDouble(x, mode); 55 } 56 57 private static class BigDecimalToDoubleRounder extends ToDoubleRounder<BigDecimal> { 58 static final BigDecimalToDoubleRounder INSTANCE = new BigDecimalToDoubleRounder(); 59 BigDecimalToDoubleRounder()60 private BigDecimalToDoubleRounder() {} 61 62 @Override roundToDoubleArbitrarily(BigDecimal bigDecimal)63 double roundToDoubleArbitrarily(BigDecimal bigDecimal) { 64 return bigDecimal.doubleValue(); 65 } 66 67 @Override sign(BigDecimal bigDecimal)68 int sign(BigDecimal bigDecimal) { 69 return bigDecimal.signum(); 70 } 71 72 @Override toX(double d, RoundingMode mode)73 BigDecimal toX(double d, RoundingMode mode) { 74 return new BigDecimal(d); 75 } 76 77 @Override minus(BigDecimal a, BigDecimal b)78 BigDecimal minus(BigDecimal a, BigDecimal b) { 79 return a.subtract(b); 80 } 81 } 82 } 83