javadoc.src-html.com.google.common.math.BigIntegerMath.html Maven / Gradle / Ivy
The newest version!
001 /*
002 * Copyright (C) 2011 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package com.google.common.math;
018
019 import static com.google.common.base.Preconditions.checkArgument;
020 import static com.google.common.base.Preconditions.checkNotNull;
021 import static com.google.common.math.MathPreconditions.checkNonNegative;
022 import static com.google.common.math.MathPreconditions.checkPositive;
023 import static com.google.common.math.MathPreconditions.checkRoundingUnnecessary;
024 import static java.math.RoundingMode.CEILING;
025 import static java.math.RoundingMode.FLOOR;
026 import static java.math.RoundingMode.HALF_EVEN;
027
028 import com.google.common.annotations.Beta;
029 import com.google.common.annotations.VisibleForTesting;
030
031 import java.math.BigDecimal;
032 import java.math.BigInteger;
033 import java.math.RoundingMode;
034 import java.util.ArrayList;
035 import java.util.List;
036
037 /**
038 * A class for arithmetic on values of type {@code BigInteger}.
039 *
040 * <p>The implementations of many methods in this class are based on material from Henry S. Warren,
041 * Jr.'s <i>Hacker's Delight</i>, (Addison Wesley, 2002).
042 *
043 * <p>Similar functionality for {@code int} and for {@code long} can be found in
044 * {@link IntMath} and {@link LongMath} respectively.
045 *
046 * @author Louis Wasserman
047 * @since 11.0
048 */
049 @Beta
050 public final class BigIntegerMath {
051 /**
052 * Returns {@code true} if {@code x} represents a power of two.
053 */
054 public static boolean isPowerOfTwo(BigInteger x) {
055 checkNotNull(x);
056 return x.signum() > 0 && x.getLowestSetBit() == x.bitLength() - 1;
057 }
058
059 /**
060 * Returns the base-2 logarithm of {@code x}, rounded according to the specified rounding mode.
061 *
062 * @throws IllegalArgumentException if {@code x <= 0}
063 * @throws ArithmeticException if {@code mode} is {@link RoundingMode#UNNECESSARY} and {@code x}
064 * is not a power of two
065 */
066 @SuppressWarnings("fallthrough")
067 public static int log2(BigInteger x, RoundingMode mode) {
068 checkPositive("x", checkNotNull(x));
069 int logFloor = x.bitLength() - 1;
070 switch (mode) {
071 case UNNECESSARY:
072 checkRoundingUnnecessary(isPowerOfTwo(x)); // fall through
073 case DOWN:
074 case FLOOR:
075 return logFloor;
076
077 case UP:
078 case CEILING:
079 return isPowerOfTwo(x) ? logFloor : logFloor + 1;
080
081 case HALF_DOWN:
082 case HALF_UP:
083 case HALF_EVEN:
084 if (logFloor < SQRT2_PRECOMPUTE_THRESHOLD) {
085 BigInteger halfPower = SQRT2_PRECOMPUTED_BITS.shiftRight(
086 SQRT2_PRECOMPUTE_THRESHOLD - logFloor);
087 if (x.compareTo(halfPower) <= 0) {
088 return logFloor;
089 } else {
090 return logFloor + 1;
091 }
092 }
093 /*
094 * Since sqrt(2) is irrational, log2(x) - logFloor cannot be exactly 0.5
095 *
096 * To determine which side of logFloor.5 the logarithm is, we compare x^2 to 2^(2 *
097 * logFloor + 1).
098 */
099 BigInteger x2 = x.pow(2);
100 int logX2Floor = x2.bitLength() - 1;
101 return (logX2Floor < 2 * logFloor + 1) ? logFloor : logFloor + 1;
102
103 default:
104 throw new AssertionError();
105 }
106 }
107
108 /*
109 * The maximum number of bits in a square root for which we'll precompute an explicit half power
110 * of two. This can be any value, but higher values incur more class load time and linearly
111 * increasing memory consumption.
112 */
113 @VisibleForTesting static final int SQRT2_PRECOMPUTE_THRESHOLD = 256;
114
115 @VisibleForTesting static final BigInteger SQRT2_PRECOMPUTED_BITS =
116 new BigInteger("16a09e667f3bcc908b2fb1366ea957d3e3adec17512775099da2f590b0667322a", 16);
117
118 /**
119 * Returns the base-10 logarithm of {@code x}, rounded according to the specified rounding mode.
120 *
121 * @throws IllegalArgumentException if {@code x <= 0}
122 * @throws ArithmeticException if {@code mode} is {@link RoundingMode#UNNECESSARY} and {@code x}
123 * is not a power of ten
124 */
125 @SuppressWarnings("fallthrough")
126 public static int log10(BigInteger x, RoundingMode mode) {
127 checkPositive("x", x);
128 if (fitsInLong(x)) {
129 return LongMath.log10(x.longValue(), mode);
130 }
131
132 // capacity of 10 suffices for all x <= 10^(2^10).
133 List<BigInteger> powersOf10 = new ArrayList<BigInteger>(10);
134 BigInteger powerOf10 = BigInteger.TEN;
135 while (x.compareTo(powerOf10) >= 0) {
136 powersOf10.add(powerOf10);
137 powerOf10 = powerOf10.pow(2);
138 }
139 BigInteger floorPow = BigInteger.ONE;
140 int floorLog = 0;
141 for (int i = powersOf10.size() - 1; i >= 0; i--) {
142 BigInteger powOf10 = powersOf10.get(i);
143 floorLog *= 2;
144 BigInteger tenPow = powOf10.multiply(floorPow);
145 if (x.compareTo(tenPow) >= 0) {
146 floorPow = tenPow;
147 floorLog++;
148 }
149 }
150 switch (mode) {
151 case UNNECESSARY:
152 checkRoundingUnnecessary(floorPow.equals(x));
153 // fall through
154 case FLOOR:
155 case DOWN:
156 return floorLog;
157
158 case CEILING:
159 case UP:
160 return floorPow.equals(x) ? floorLog : floorLog + 1;
161
162 case HALF_DOWN:
163 case HALF_UP:
164 case HALF_EVEN:
165 // Since sqrt(10) is irrational, log10(x) - floorLog can never be exactly 0.5
166 BigInteger x2 = x.pow(2);
167 BigInteger halfPowerSquared = floorPow.pow(2).multiply(BigInteger.TEN);
168 return (x2.compareTo(halfPowerSquared) <= 0) ? floorLog : floorLog + 1;
169 default:
170 throw new AssertionError();
171 }
172 }
173
174 /**
175 * Returns the square root of {@code x}, rounded with the specified rounding mode.
176 *
177 * @throws IllegalArgumentException if {@code x < 0}
178 * @throws ArithmeticException if {@code mode} is {@link RoundingMode#UNNECESSARY} and
179 * {@code sqrt(x)} is not an integer
180 */
181 @SuppressWarnings("fallthrough")
182 public static BigInteger sqrt(BigInteger x, RoundingMode mode) {
183 checkNonNegative("x", x);
184 if (fitsInLong(x)) {
185 return BigInteger.valueOf(LongMath.sqrt(x.longValue(), mode));
186 }
187 BigInteger sqrtFloor = sqrtFloor(x);
188 switch (mode) {
189 case UNNECESSARY:
190 checkRoundingUnnecessary(sqrtFloor.pow(2).equals(x)); // fall through
191 case FLOOR:
192 case DOWN:
193 return sqrtFloor;
194 case CEILING:
195 case UP:
196 return sqrtFloor.pow(2).equals(x) ? sqrtFloor : sqrtFloor.add(BigInteger.ONE);
197 case HALF_DOWN:
198 case HALF_UP:
199 case HALF_EVEN:
200 BigInteger halfSquare = sqrtFloor.pow(2).add(sqrtFloor);
201 /*
202 * We wish to test whether or not x <= (sqrtFloor + 0.5)^2 = halfSquare + 0.25. Since both
203 * x and halfSquare are integers, this is equivalent to testing whether or not x <=
204 * halfSquare.
205 */
206 return (halfSquare.compareTo(x) >= 0) ? sqrtFloor : sqrtFloor.add(BigInteger.ONE);
207 default:
208 throw new AssertionError();
209 }
210 }
211
212 private static BigInteger sqrtFloor(BigInteger x) {
213 /*
214 * Adapted from Hacker's Delight, Figure 11-1.
215 *
216 * Using DoubleUtils.bigToDouble, getting a double approximation of x is extremely fast, and
217 * then we can get a double approximation of the square root. Then, we iteratively improve this
218 * guess with an application of Newton's method, which sets guess := (guess + (x / guess)) / 2.
219 * This iteration has the following two properties:
220 *
221 * a) every iteration (except potentially the first) has guess >= floor(sqrt(x)). This is
222 * because guess' is the arithmetic mean of guess and x / guess, sqrt(x) is the geometric mean,
223 * and the arithmetic mean is always higher than the geometric mean.
224 *
225 * b) this iteration converges to floor(sqrt(x)). In fact, the number of correct digits doubles
226 * with each iteration, so this algorithm takes O(log(digits)) iterations.
227 *
228 * We start out with a double-precision approximation, which may be higher or lower than the
229 * true value. Therefore, we perform at least one Newton iteration to get a guess that's
230 * definitely >= floor(sqrt(x)), and then continue the iteration until we reach a fixed point.
231 */
232 BigInteger sqrt0;
233 int log2 = log2(x, FLOOR);
234 if(log2 < DoubleUtils.MAX_DOUBLE_EXPONENT) {
235 sqrt0 = sqrtApproxWithDoubles(x);
236 } else {
237 int shift = (log2 - DoubleUtils.SIGNIFICAND_BITS) & ~1; // even!
238 /*
239 * We have that x / 2^shift < 2^54. Our initial approximation to sqrtFloor(x) will be
240 * 2^(shift/2) * sqrtApproxWithDoubles(x / 2^shift).
241 */
242 sqrt0 = sqrtApproxWithDoubles(x.shiftRight(shift)).shiftLeft(shift >> 1);
243 }
244 BigInteger sqrt1 = sqrt0.add(x.divide(sqrt0)).shiftRight(1);
245 if (sqrt0.equals(sqrt1)) {
246 return sqrt0;
247 }
248 do {
249 sqrt0 = sqrt1;
250 sqrt1 = sqrt0.add(x.divide(sqrt0)).shiftRight(1);
251 } while (sqrt1.compareTo(sqrt0) < 0);
252 return sqrt0;
253 }
254
255 private static BigInteger sqrtApproxWithDoubles(BigInteger x) {
256 return DoubleMath.roundToBigInteger(Math.sqrt(DoubleUtils.bigToDouble(x)), HALF_EVEN);
257 }
258
259 /**
260 * Returns the result of dividing {@code p} by {@code q}, rounding using the specified
261 * {@code RoundingMode}.
262 *
263 * @throws ArithmeticException if {@code q == 0}, or if {@code mode == UNNECESSARY} and {@code a}
264 * is not an integer multiple of {@code b}
265 */
266 public static BigInteger divide(BigInteger p, BigInteger q, RoundingMode mode){
267 BigDecimal pDec = new BigDecimal(p);
268 BigDecimal qDec = new BigDecimal(q);
269 return pDec.divide(qDec, 0, mode).toBigIntegerExact();
270 }
271
272 /**
273 * Returns {@code n!}, that is, the product of the first {@code n} positive
274 * integers, or {@code 1} if {@code n == 0}.
275 *
276 * <p><b>Warning</b>: the result takes <i>O(n log n)</i> space, so use cautiously.
277 *
278 * <p>This uses an efficient binary recursive algorithm to compute the factorial
279 * with balanced multiplies. It also removes all the 2s from the intermediate
280 * products (shifting them back in at the end).
281 *
282 * @throws IllegalArgumentException if {@code n < 0}
283 */
284 public static BigInteger factorial(int n) {
285 checkNonNegative("n", n);
286
287 // If the factorial is small enough, just use LongMath to do it.
288 if (n < LongMath.FACTORIALS.length) {
289 return BigInteger.valueOf(LongMath.FACTORIALS[n]);
290 }
291
292 // Pre-allocate space for our list of intermediate BigIntegers.
293 int approxSize = IntMath.divide(n * IntMath.log2(n, CEILING), Long.SIZE, CEILING);
294 ArrayList<BigInteger> bignums = new ArrayList<BigInteger>(approxSize);
295
296 // Start from the pre-computed maximum long factorial.
297 int startingNumber = LongMath.FACTORIALS.length;
298 long product = LongMath.FACTORIALS[startingNumber - 1];
299 // Strip off 2s from this value.
300 int shift = Long.numberOfTrailingZeros(product);
301 product >>= shift;
302
303 // Use floor(log2(num)) + 1 to prevent overflow of multiplication.
304 int productBits = LongMath.log2(product, FLOOR) + 1;
305 int bits = LongMath.log2(startingNumber, FLOOR) + 1;
306 // Check for the next power of two boundary, to save us a CLZ operation.
307 int nextPowerOfTwo = 1 << (bits - 1);
308
309 // Iteratively multiply the longs as big as they can go.
310 for (long num = startingNumber; num <= n; num++) {
311 // Check to see if the floor(log2(num)) + 1 has changed.
312 if ((num & nextPowerOfTwo) != 0) {
313 nextPowerOfTwo <<= 1;
314 bits++;
315 }
316 // Get rid of the 2s in num.
317 int tz = Long.numberOfTrailingZeros(num);
318 long normalizedNum = num >> tz;
319 shift += tz;
320 // Adjust floor(log2(num)) + 1.
321 int normalizedBits = bits - tz;
322 // If it won't fit in a long, then we store off the intermediate product.
323 if (normalizedBits + productBits >= Long.SIZE) {
324 bignums.add(BigInteger.valueOf(product));
325 product = 1;
326 productBits = 0;
327 }
328 product *= normalizedNum;
329 productBits = LongMath.log2(product, FLOOR) + 1;
330 }
331 // Check for leftovers.
332 if (product > 1) {
333 bignums.add(BigInteger.valueOf(product));
334 }
335 // Efficiently multiply all the intermediate products together.
336 return listProduct(bignums).shiftLeft(shift);
337 }
338
339 static BigInteger listProduct(List<BigInteger> nums) {
340 return listProduct(nums, 0, nums.size());
341 }
342
343 static BigInteger listProduct(List<BigInteger> nums, int start, int end) {
344 switch (end - start) {
345 case 0:
346 return BigInteger.ONE;
347 case 1:
348 return nums.get(start);
349 case 2:
350 return nums.get(start).multiply(nums.get(start + 1));
351 case 3:
352 return nums.get(start).multiply(nums.get(start + 1)).multiply(nums.get(start + 2));
353 default:
354 // Otherwise, split the list in half and recursively do this.
355 int m = (end + start) >>> 1;
356 return listProduct(nums, start, m).multiply(listProduct(nums, m, end));
357 }
358 }
359
360 /**
361 * Returns {@code n} choose {@code k}, also known as the binomial coefficient of {@code n} and
362 * {@code k}, that is, {@code n! / (k! (n - k)!)}.
363 *
364 * <p><b>Warning</b>: the result can take as much as <i>O(k log n)</i> space.
365 *
366 * @throws IllegalArgumentException if {@code n < 0}, {@code k < 0}, or {@code k > n}
367 */
368 public static BigInteger binomial(int n, int k) {
369 checkNonNegative("n", n);
370 checkNonNegative("k", k);
371 checkArgument(k <= n, "k (%s) > n (%s)", k, n);
372 if (k > (n >> 1)) {
373 k = n - k;
374 }
375 if (k < LongMath.BIGGEST_BINOMIALS.length && n <= LongMath.BIGGEST_BINOMIALS[k]) {
376 return BigInteger.valueOf(LongMath.binomial(n, k));
377 }
378 BigInteger result = BigInteger.ONE;
379 for (int i = 0; i < k; i++) {
380 result = result.multiply(BigInteger.valueOf(n - i));
381 result = result.divide(BigInteger.valueOf(i + 1));
382 }
383 return result;
384 }
385
386 // Returns true if BigInteger.valueOf(x.longValue()).equals(x).
387 static boolean fitsInLong(BigInteger x) {
388 return x.bitLength() <= Long.SIZE - 1;
389 }
390
391 private BigIntegerMath() {}
392 }
© 2015 - 2025 Weber Informatics LLC | Privacy Policy