BigDecimal.add странное поведение
Метод BigDecimal.add
занимает много времени, когда один аргумент имеет большой показатель (9 цифр), а второй имеет показатель с разной длиной. Я ждал более 5 минут, и он продолжался и продолжался.
Здесь код:
@Test
public void testAddBig() throws Exception {
MathContext mc = new MathContext(10, RoundingMode.HALF_UP);
BigDecimal v1 = new BigDecimal("1E+100000000", mc);
BigDecimal v2 = new BigDecimal("1", mc);
System.out.println(v1.add(v2));
}
Здесь часть дампа потока:
at java.math.BigInteger.square(BigInteger.java:1884)
at java.math.BigInteger.squareKaratsuba(BigInteger.java:1975)
at java.math.BigInteger.square(BigInteger.java:1888)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2011)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2006)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2012)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2010)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2006)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2012)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2011)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.pow(BigInteger.java:2263)
at java.math.BigDecimal.bigTenToThe(BigDecimal.java:3543)
at java.math.BigDecimal.bigMultiplyPowerTen(BigDecimal.java:4508)
at java.math.BigDecimal.add(BigDecimal.java:4443)
at java.math.BigDecimal.add(BigDecimal.java:1289)
Что происходит? Это ошибка?
Ответы
Ответ 1
Хорошо, чтобы ответить на это просто. BigNumbers работают с массивом символов, чтобы обеспечить максимальную точность. Поскольку ваш номер будет состоять из 100000000 цифр, это будет длина вашего массива.
100.000.000 символов = байты
Это 100 МБ, если я не ошибаюсь. Затем вы хотите сделать математику с этим, это начало много читать;)
Если вы откроете класс BigDecimal, вы увидите, что существует множество проверок, поскольку это "письмо", а не цифры.
BigDecimal полезны для поддержания точности, но это делается за небольшую плату, здесь память и время обработки.
ИЗМЕНИТЬ:
Это будет проблемой только в том случае, если вы используете экземпляр в некотором роде, конструктор сохранит это значение как показатель экспоненты 1E + ***. Если вы его распечатаете, это будет нормально, но если вы попросите числовое значение, это начнет сбой.
Чтобы быть более точным, BigDecimal.bigTenToThe(int)
получит значение экспоненты (1000000000).
private static BigInteger bigTenToThe(int n) {
...
char tenpow[] = new char[n + 1];
....
}