Подтвердить что ты не робот

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)

Что происходит? Это ошибка?

4b9b3361

Ответ 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];
    ....
}