Как я уже говорил ранее в посте Sneaking a Peek at Guava Release 11 , Guava Release 11 предоставляет множество новых классов, включая несколько классов, специально связанных с математическими операциями. В этой статье я расскажу об одном из них, который нацелен на целочисленную математику: Guava ‘s IntMath .
Как указано в моем предыдущем посте, com.google.common.math.IntMath в значительной степени основана на Генри С. Уоррен, младший «S Хакера Delight . Как указывает имя класса, операции этого класса сосредоточены на «арифметике значений типа int».
На следующем снимке экрана показаны методы и статические атрибуты, поддерживаемые IntMath, как указано в javap :
Для удобства я перечислил текстовую версию вышеупомянутого вывода javap здесь.
Compiled from "IntMath.java"
public final class com.google.common.math.IntMath {
static final int MAX_POWER_OF_SQRT2_UNSIGNED;
static final int[] POWERS_OF_10;
static final int[] HALF_POWERS_OF_10;
static final int FLOOR_SQRT_MAX_INT;
static final int[] FACTORIALS;
static int[] BIGGEST_BINOMIALS;
public static boolean isPowerOfTwo(int);
public static int log2(int, java.math.RoundingMode);
public static int log10(int, java.math.RoundingMode);
public static int pow(int, int);
public static int sqrt(int, java.math.RoundingMode);
public static int divide(int, int, java.math.RoundingMode);
public static int mod(int, int);
public static int gcd(int, int);
public static int checkedAdd(int, int);
public static int checkedSubtract(int, int);
public static int checkedMultiply(int, int);
public static int checkedPow(int, int);
public static int factorial(int);
public static int binomial(int, int);
static {};
}
Как показывают вышеприведенные изображения и текстовые данные, класс IntMath может многое предложить с точки зрения функциональности, связанной с целочисленной арифметикой. Остальная часть этого поста продемонстрирует это.
Факторный расчет обычно применяется в примерах разработки программного обеспечения, особенно в академических контекстах, таких как иллюстрирование рекурсии . Сообщение в блоге Реализация факториальной функции с использованием Java и Guava посвящено различным реализациям факториала, реализованным в Java и Guava. Guava Release 11 теперь предоставляет метод вычисления факториала в IntMath.factorial (int) .
Guava’s IntMath.factorial (int), продемонстрированный
/**
* Demonstrate factorial calculation.
*/
public static void demoFactorial()
{
final int x = 5;
final int factorial = IntMath.factorial(x);
out.println("Factorial of x=" + x + " is " + factorial);
}
Другой часто математической операцией, поддерживаемой Guava Release 11, является вычисление биномиального коэффициента через IntMath.binomial (int, int) .
Guava’s IntMath.binomial (int, int), продемонстрированный
/**
* Demonstrate binomial Coefficient calculation
* (http://en.wikipedia.org/wiki/Binomial_coefficient).
*/
public static void demoBinomialCoefficient()
{
final int n = 5;
final int k = 3;
final int binomialCoefficient = IntMath.binomial(n, k);
out.println(
"Binomial Coefficient of n=" + n + " and k=" + k + " is "
+ binomialCoefficient);
}
Guava Release 11 также добавляет метод для вычисления наибольшего общего делителя двух предоставленных целых чисел.
Guava’s IntMath.gcd (int, int), продемонстрированный
/**
* Demonstrate calculation of greatest common factor (GCF) [called greatest
* common divisor here].
*/
public static void demoGreatestCommonFactor()
{
final int x = 30;
final int y = 45;
final int gcf = IntMath.gcd(x, y);
out.println("GCF of " + x + " and " + y + " is " + gcf);
}
Релиз 11 в Guava предоставляет метод для вычисления целочисленного квадратного корня из предоставленного целого числа, округляя до целочисленного результата, когда это необходимо, на основе предоставленного RoundingMode . Тот факт, что результатом функции квадратного корня является целое число, отличает этот метод от Math.sqrt (double) .
Guava’s IntMath.sqrt (int) продемонстрировано
/**
* Demonstrate calculation of square roots.
*/
public static void demoSquareRoot()
{
final int x = 16;
final int sqrtX = IntMath.sqrt(x, RoundingMode.HALF_EVEN);
out.println("Square root of " + x + " is " + sqrtX);
final int y = 25;
final int sqrtY = IntMath.sqrt(y, RoundingMode.HALF_EVEN);
out.println("Square root of " + y + " is " + sqrtY);
}
IntMath в версии 11 релиза Guava предоставляет метод pow (int, int) для первого целого числа, умноженного на себя число раз, выраженное вторым целым числом (аналогично Math.pow (double, double)) , но принимающее и возвращающее целые числа, а не удваивающиеся. ). Метод IntMath.pow (int, int) обеспечивает обработку ситуаций, в которых операция обычно приводит к переполнению. В такой ситуации, согласно Javadoc метода , метод вернет результат, который «будет равен BigInteger.valueOf (b) .pow (k) .intValue ()».
Guava’s IntMath.pow (int, int), продемонстрированный
/**
* Demonstrate exponential power calculation.
*/
public static void demoExponentialPower()
{
final int base = 2;
final int exponent = 5;
final int result = IntMath.pow(base, exponent);
out.println(base + " to power of " + exponent + " is " + result);
}
Особенно интересный метод, который предоставляет Guava Release 11, который может быть особенно полезен в определенных разработках программного обеспечения и компьютерных контекстах, — это метод IntMath.isPowerOfTwo (int) . Этот метод возвращает логическое значение, указывающее, является ли предоставленное целое число равномерно делимым (без остатка) на два.
Guava’s IntMath.isPowerOfTwo (int) Демонстрируется
/**
* Demonstrate determination of whether an integer is a power of two.
*/
public static void demoIsPowerOfTwo()
{
final int x = 16;
out.println(x + (IntMath.isPowerOfTwo(x) ? " IS " : " is NOT " ) + " a power of two.");
final int y = 31;
out.println(y + (IntMath.isPowerOfTwo(y) ? " IS " : " is NOT " ) + " a power of two.");
}
Класс IntMath в Guava предоставляет два метода для выполнения логарифмических вычислений, уделяя особое внимание общему логарифму (основание 10) и двоичному логарифму (основание 2). Оба из них продемонстрированы в следующем листинге кода.
IntMath.log10 в Guava (int, RoundingMode) и IntMath.log2 (int, RoundingMode) продемонстрированы
/**
* Demonstrate IntMath.log10 and IntMath.log2.
*/
public static void demoLogarithmicFunctions()
{
final int x = 10000000;
final int resultX = IntMath.log10(x, RoundingMode.HALF_EVEN);
out.println("Logarithm (base 10) of " + x + " is " + resultX);
final int y = 32;
final int resultY = IntMath.log2(y, RoundingMode.HALF_EVEN);
out.println("Logarithm (base 2) of " + y + " is " + resultY);
}
IntMath.divide версии 11 для Guava (int, int, RoundingMode) допускает целочисленное деление, при котором тип округления, используемый в делении, может быть указан как часть вызова. Это более гибко, чем прямое целочисленное деление Java, которое всегда округляет частное до нижнего целого (минимальное).
IntMath.divide в Guava (int, int, RoundingMode) Демонстрируется
/**
* Demonstrate division using IntMath.divide.
*/
public static void demoDivision()
{
final int dividend = 30;
final int divisor = 10;
final int quotient = IntMath.divide(dividend, divisor, RoundingMode.HALF_EVEN);
out.println(dividend + " / " + divisor + " = " + quotient);
}
Ранее я упоминал, что IntMath.pow (int, int) в Guava версии 11 будет обрабатывать ситуации переполнения, возвращая «BigInteger.valueOf (b) .pow (k) .intValue ()», где «b» — это первое целое число (основание) и ‘k’ — второе целое число (степень / показатель степени). В некоторых случаях может быть предпочтительным создать исключение при возникновении ситуации переполнения, а не «скрывать» проблему. В таких случаях желательно использовать IntMath.checkedPow (int, int) из Guava Release 11, поскольку он вызывает исключение ArithmeticException, если операция приводит к переполнению.
IntMath.checkedPow (int, int) Демонстрируется
/**
* Demonstrate Guava Release 11's checked power method and compare it to
* other common approaches for determining base multiplied by itself exponent
* number of times.
*/
public static void demoCheckedPower()
{
try
{
final int base = 2;
final int exponent = 4;
final int result = IntMath.checkedPow(base, exponent);
out.println("IntMath.checkedPow: " + base + "^" + exponent + " = " + result);
out.println(
"IntMath.pow: " + Integer.MAX_VALUE + "^2 = " +
+ IntMath.pow(Integer.MAX_VALUE, 2));
out.println(
"Math.pow(int,int): " + Integer.MAX_VALUE + "^2 = "
+ Math.pow(Integer.MAX_VALUE, 2));
out.println("Multiplied: " + Integer.MAX_VALUE*Integer.MAX_VALUE);
out.print("IntMath.checkedPow: " + Integer.MAX_VALUE + "^2 = ");
out.println(IntMath.checkedPow(Integer.MAX_VALUE, 2));
}
catch (Exception ex)
{
err.println("Exception during power: " + ex.toString());
}
}
Класс IntMath версии 11 в Guava предоставляет еще три «проверенных» метода, которые выдают исключение ArithmeticException, когда данная математическая операция приводит к состоянию переполнения. Эти методы предназначены для сложения, вычитания и умножения и соответственно называются IntMath.checkedAdd (int, int) , IntMath.checkedSubtract (int, int) и IntMath.checkedMultiply (int, int) . Как обсуждалось в связи с IntMath.checkedPow (int, int), преимущество этого происходит в ситуациях, когда лучше иметь исключение и знать, что произошло переполнение, чем слепо работать с ошибочным значением из-за условия переполнения.
Демонстрация в Guava: selectedAdd (int, int), checkedSubtract (int, int) и checkMultiply (int, int)
/**
* Demonstrate Guava Release 11's checked addition method.
*/
public static void demoCheckedAddition()
{
try
{
final int augend = 20;
final int addend = 10;
final int sum = IntMath.checkedAdd(augend, addend);
out.println(augend + " + " + addend + " = " + sum);
final int overflowSum = IntMath.checkedAdd(Integer.MAX_VALUE, 1);
out.println(Integer.MAX_VALUE + " + 1 = " + overflowSum);
}
catch (Exception ex)
{
err.println("Exception during addition: " + ex.toString());
}
}
/**
* Demonstrate Guava Release 11's checked subtraction method.
*/
public static void demoCheckedSubtraction()
{
try
{
final int minuend = 30;
final int subtrahend = 20;
final int difference = IntMath.checkedSubtract(minuend, subtrahend);
out.println(minuend + " - " + subtrahend + " = " + difference);
final int overflowDifference = IntMath.checkedSubtract(Integer.MIN_VALUE, 1);
out.println(Integer.MIN_VALUE + " - 1 = " + overflowDifference);
}
catch (Exception ex)
{
err.println("Exception during subtraction: " + ex.toString());
}
}
/**
* Demonstrate Guava Release 11's checked multiplication method.
*/
public static void demoCheckedMultiplication()
{
try
{
final int factor1 = 3;
final int factor2 = 10;
final int product = IntMath.checkedMultiply(factor1, factor2);
out.println(factor1 + " * " + factor2 + " = " + product);
final int overflowProduct = IntMath.checkedMultiply(Integer.MAX_VALUE, 2);
out.println(Integer.MAX_VALUE + " * 2 = " + overflowProduct);
}
catch (Exception ex)
{
err.println("Exception during multiplication: " + ex.toString());
}
}
В блоге « Обработка очень больших чисел в Java» рассказывается о проблемах с большими числами в Java и возможном переполнении. Как рекомендует этот пост, для таких ситуаций часто рекомендуется использовать BigInteger и BigDecimal . Однако эти новые «проверенные» методы Guava IntMath предоставляют другую альтернативу для разработчика Java, который хочет иметь дело с целыми числами, но знает, когда произошло переполнение.
Я показал простые примеры использования большинства методов нового класса IntMath в выпуске Guava 11 [я не обсуждал и не показывал IntMath.mod (int, int) ]. Следующий листинг кода связывает все вышеприведенные примеры вместе и сопровождается выводом из этого листинга.
UsingIntMath.java
package dustin.examples;
import static java.lang.System.err;
import static java.lang.System.out;
import com.google.common.math.IntMath;
import java.math.RoundingMode;
/**
* Simple examples of using Guava Release 11's {@code IntMath} class.
*
* @author Dustin
*/
public class UsingIntMath
{
/**
* Demonstrate binomial Coefficient calculation
* (http://en.wikipedia.org/wiki/Binomial_coefficient).
*/
public static void demoBinomialCoefficient()
{
final int n = 5;
final int k = 3;
final int binomialCoefficient = IntMath.binomial(n, k);
out.println(
"Binomial Coefficient of n=" + n + " and k=" + k + " is "
+ binomialCoefficient);
}
/**
* Demonstrate factorial calculation.
*/
public static void demoFactorial()
{
final int x = 5;
final int factorial = IntMath.factorial(x);
out.println("Factorial of x=" + x + " is " + factorial);
}
/**
* Demonstrate calculation of greatest common factor (GCF) [called greatest
* common divisor here].
*/
public static void demoGreatestCommonFactor()
{
final int x = 30;
final int y = 45;
final int gcf = IntMath.gcd(x, y);
out.println("GCF of " + x + " and " + y + " is " + gcf);
}
/**
* Demonstrate calculation of square roots.
*/
public static void demoSquareRoot()
{
final int x = 16;
final int sqrtX = IntMath.sqrt(x, RoundingMode.HALF_EVEN);
out.println("Square root of " + x + " is " + sqrtX);
final int y = 25;
final int sqrtY = IntMath.sqrt(y, RoundingMode.HALF_EVEN);
out.println("Square root of " + y + " is " + sqrtY);
}
/**
* Demonstrate determination of whether an integer is a power of two.
*/
public static void demoIsPowerOfTwo()
{
final int x = 16;
out.println(x + (IntMath.isPowerOfTwo(x) ? " IS " : " is NOT " ) + " a power of two.");
final int y = 31;
out.println(y + (IntMath.isPowerOfTwo(y) ? " IS " : " is NOT " ) + " a power of two.");
}
/**
* Demonstrate exponential power calculation.
*/
public static void demoExponentialPower()
{
final int base = 2;
final int exponent = 5;
final int result = IntMath.pow(base, exponent);
out.println(base + " to power of " + exponent + " is " + result);
}
/**
* Demonstrate IntMath.log10 and IntMath.log2.
*/
public static void demoLogarithmicFunctions()
{
final int x = 10000000;
final int resultX = IntMath.log10(x, RoundingMode.HALF_EVEN);
out.println("Logarithm (base 10) of " + x + " is " + resultX);
final int y = 32;
final int resultY = IntMath.log2(y, RoundingMode.HALF_EVEN);
out.println("Logarithm (base 2) of " + y + " is " + resultY);
}
/**
* Demonstrate Guava Release 11's checked addition method.
*/
public static void demoCheckedAddition()
{
try
{
final int augend = 20;
final int addend = 10;
final int sum = IntMath.checkedAdd(augend, addend);
out.println(augend + " + " + addend + " = " + sum);
final int overflowSum = IntMath.checkedAdd(Integer.MAX_VALUE, 1);
out.println(Integer.MAX_VALUE + " + 1 = " + overflowSum);
}
catch (Exception ex)
{
err.println("Exception during addition: " + ex.toString());
}
}
/**
* Demonstrate Guava Release 11's checked subtraction method.
*/
public static void demoCheckedSubtraction()
{
try
{
final int minuend = 30;
final int subtrahend = 20;
final int difference = IntMath.checkedSubtract(minuend, subtrahend);
out.println(minuend + " - " + subtrahend + " = " + difference);
final int overflowDifference = IntMath.checkedSubtract(Integer.MIN_VALUE, 1);
out.println(Integer.MIN_VALUE + " - 1 = " + overflowDifference);
}
catch (Exception ex)
{
err.println("Exception during subtraction: " + ex.toString());
}
}
/**
* Demonstrate Guava Release 11's checked multiplication method.
*/
public static void demoCheckedMultiplication()
{
try
{
final int factor1 = 3;
final int factor2 = 10;
final int product = IntMath.checkedMultiply(factor1, factor2);
out.println(factor1 + " * " + factor2 + " = " + product);
final int overflowProduct = IntMath.checkedMultiply(Integer.MAX_VALUE, 2);
out.println(Integer.MAX_VALUE + " * 2 = " + overflowProduct);
}
catch (Exception ex)
{
err.println("Exception during multiplication: " + ex.toString());
}
}
/**
* Demonstrate Guava Release 11's checked power method and compare it to
* other common approaches for determining base multiplied by itself exponent
* number of times.
*/
public static void demoCheckedPower()
{
try
{
final int base = 2;
final int exponent = 4;
final int result = IntMath.checkedPow(base, exponent);
out.println("IntMath.checkedPow: " + base + "^" + exponent + " = " + result);
out.println(
"IntMath.pow: " + Integer.MAX_VALUE + "^2 = " +
+ IntMath.pow(Integer.MAX_VALUE, 2));
out.println(
"Math.pow(int,int): " + Integer.MAX_VALUE + "^2 = "
+ Math.pow(Integer.MAX_VALUE, 2));
out.println("Multiplied: " + Integer.MAX_VALUE*Integer.MAX_VALUE);
out.print("IntMath.checkedPow: " + Integer.MAX_VALUE + "^2 = ");
out.println(IntMath.checkedPow(Integer.MAX_VALUE, 2));
}
catch (Exception ex)
{
err.println("Exception during power: " + ex.toString());
}
}
/**
* Demonstrate division using IntMath.divide.
*/
public static void demoDivision()
{
final int dividend = 30;
final int divisor = 10;
final int quotient = IntMath.divide(dividend, divisor, RoundingMode.HALF_EVEN);
out.println(dividend + " / " + divisor + " = " + quotient);
}
/**
* Main function for demonstrating Guava Release 11's {@code IntMath} class.
*
* @param arguments Command-line arguments; none expected.
*/
public static void main(final String[] arguments)
{
demoBinomialCoefficient();
demoFactorial();
demoGreatestCommonFactor();
demoSquareRoot();
demoIsPowerOfTwo();
demoExponentialPower();
demoLogarithmicFunctions();
demoCheckedAddition();
demoCheckedSubtraction();
demoCheckedMultiplication();
demoCheckedPower();
demoDivision();
}
}
В этом сообщении была предпринята попытка продемонстрировать полезность и простоту использования, предоставляемые классом IntMath в версии 11 для Guava. Этот класс предоставляет множество удобных методов для упрощения общих математических операций над целыми числами. 11-й выпуск Guava предоставляет в основном те же методы в пакете com.google.common.math для longs ( LongMath ) и аналогичные методы для double ( DoubleMath ) и BigIntegers ( BigIntegerMath ).
От http://marxsoftware.blogspot.com/2011/12/guava-release-11s-intmath.html

