Я работаю над проблемой 29 Project Euler, в которой говорится:

Рассмотрим все целые комбинации a ^ b для 2 ≤ a ≤ 5 и 2 ≤ b ≤ 5:

2 ^ 2 = 4, 2 ^ 3 = 8, 2 ^ 4 = 16, 2 ^ 5 = 32

3 ^ 2 = 9, 3 ^ 3 = 27, 3 ^ 4 = 81, 3 ^ 5 = 243

4 ^ 2 = 16, 4 ^ 3 = 64, 4 ^ 4 = 256, 4 ^ 5 = 1024

5 ^ 2 = 25, 5 ^ 3 = 125, 5 ^ 4 = 625, 5 ^ 5 = 3125

Если они затем расположены в числовом порядке, с удаленными повторениями, мы получаем следующую последовательность из 15 различных терминов:

4, 8, 9, 16, 25, 27, 32, 64, 81, 125, 243, 256, 625, 1024, 3125

Сколько различных терминов содержится в последовательности, генерируемой ab для 2 ≤ a ≤ 100 и 2 ≤ b ≤ 100?

Я написал программу для решения этой проблемы на Java. он работает без ошибок, однако не дает ожидаемого результата. Я предоставил свой код и результат ниже.

import java.util.ArrayList;
import java.math.BigInteger;
public class problemTwentyNine {
  public static void main(String [] args) {
    long start = System.nanoTime();
    ArrayList<BigInteger> distinctTerms = new ArrayList<BigInteger>();
    BigInteger temp;
    for(int i = 2; i <= 100; i++) {
      for(int j = 2; j <= 100; j++) {
        temp = new BigInteger("" + (int) (Math.pow(i, j)));
        if(!distinctTerms.contains(temp)) {
          distinctTerms.add(temp);
        }
      }
    }
    System.out.println(distinctTerms.size());
    long stop = System.nanoTime();
    System.out.println("Execution time: " + ((stop - start) / 1e+6) + "ms");
  }
}

Выход:

422

Время выполнения: 24,827827 мс

После ввода этого ответа в проект euler мы видим, что он неверен; но я не вижу, где я ошибся в своем коде.

3
James 12 Мар 2015 в 20:49

2 ответа

Лучший ответ

Причина, по которой вы получаете только 422 различных элемента, заключается в том, что ваши значения такие большие, и вы преобразуете их в int.

Когда результат Math.pow(i, j) (double) больше, чем Integer.MAX_VALUE, и вы приводите к int, то результатом будет Integer.MAX_VALUE.

Раздел 5.1.3 JLS охватывает это сужающее примитивное преобразование :

В противном случае один из следующих двух случаев должен быть истинным:

  • Значение должно быть слишком маленьким (отрицательное значение большой величины или отрицательная бесконечность), а результатом первого шага будет наименьшее представимое значение типа int или long.

  • Значение должно быть слишком большим (положительное значение большой величины или положительная бесконечность), а результатом первого шага будет наибольшее представимое значение типа int или long.

(курсив мой)

Вы получаете этот результат много, поэтому есть только 422 различных результата.

Измените свой расчет на математический BigInteger.

temp = new BigInteger("" + i).pow(j);

С этим изменением у меня теперь 9 183 различных элемента. Это имеет больше смысла, поскольку некоторые степени полных квадратов будут повторяться.

4
Community 20 Июн 2020 в 09:12

Линия (int) (Math.pow(i, j)) не имеет большого смысла, поскольку 100^100 намного больше, чем Integer.MAX_VALUE. Вы должны выполнять полномочия, используя BigInteger.

Должен быть

temp = BigInteger.valueOf(i).pow(j);
4
Paul Boddington 12 Мар 2015 в 18:00