Неверный результат Java Math.pow - PullRequest
12 голосов
/ 31 марта 2012

Если вы попытаетесь запустить следующий код

public class Main {
   public static void main(String[] args) {
       long a = (long)Math.pow(13, 15);
       System.out.println(a + " " + a%13);
   }
}

Вы получите "51185893014090752 8"

Правильное значение 13 ^ 15 равно 51185893014090757 , т.е. больше, чем результат, возвращаемый Math.pow на 5 . Любые идеи о том, что может вызвать это?

Ответы [ 6 ]

10 голосов
/ 31 марта 2012

Вы превысили количество значащих цифр (~ 15–16) в значениях с плавающей запятой двойной точности.Как только вы это сделаете, вы не можете ожидать, что младшая значащая цифра (ы) вашего результата будет действительно значимой / точной.

Если вам нужна произвольно точная арифметика в Java, рассмотрите возможность использования BigInteger и BigDecimal.

6 голосов
/ 31 марта 2012

Проблема в том, что по мере того, как вы получаете более высокие и более высокие значения double, разрыв между последовательными значениями увеличивается - double не может представлять каждое целое значение в пределах своего диапазона, и это то, что здесь происходит неправильно. Он возвращает ближайшее double значение к точному результату.

5 голосов
/ 18 февраля 2014

Это не проблема точности.Метод Math.pow выполняет аппроксимацию результата.Для получения правильного результата используйте следующий код.

long b = 13;
for(int i = 0; i != 14; i ++) {
    b = b * 13;
}
System.out.println(b);

Вывод - ожидаемый результат 51185893014090757L.

В более общем случае следует избегать использования метода Math.pow, если показатель степени равенцелое число.Во-первых, результат является приблизительным, а во-вторых, его вычисление обходится дороже.

Реализация Math.pow (и большинства других методов в классе Math) основана на сетевой библиотеке netlib в качестве пакета "Свободно распространяемая математическая библиотека »(см. StrictMath javadoc ).Реализация на C доступна по адресу e_pow.c .

1 голос
/ 31 марта 2012

Двойной имеет конечную точность, его мантисса составляет 52 бита, что примерно равно 15-16 десятичных знаков. Таким образом, число, которое вы пытаетесь вычислить, больше не может быть представлено (точно) двойным.

0 голосов
/ 31 марта 2012

это из-за ограничения удержания цифр в long путем приведения к двойному типу, с плавающей точкой вы можете это сделать, но у вас будут некоторые ошибки, вы должны сами обработать цифры вычисления, сохранив их в массиве, который не является простым способ

но в языке программирования Python вы можете получить результат любой длины, он настолько мощный!

будь успешным !!!

0 голосов
/ 31 марта 2012

Правильный ответ - указать ближайшее число, которое может быть представлено как double

Вы проверили, так ли это на самом деле?

...