• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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