Используя потоки Java, чтобы найти, является ли число простым или нет - PullRequest
0 голосов
/ 23 декабря 2018

Я читаю Взламывая Интервью по кодированию , и у него есть пример нахождения простого числа, которое я запустил на JShell

boolean isPrime(int n) {
  for (int i = 2; i * i <= n; i++) {
    if (n % i == 0) {
      return false;
    }
  }
  return true;
}

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

boolean isPrimeStream(int n) {
  return IntStream.range(0, n) // how to do similar to for loop above
    .anyMatch(i -> n % i == 0);  // i think this is the reason for failure
}

Ответы [ 3 ]

0 голосов
/ 23 декабря 2018

Проблема первая, вы должны использовать noneMatch (не anyMatch).Проблема вторая, ваш диапазон выключен.Используйте rangeClosed (или добавьте один к своему концу), который должен быть квадратным корнем из n (не просто n) - и вы начали с 2 в качестве начального значения в вашем первом тесте.Также вы можете сделать метод static.Например,

static boolean isPrimeStream(int n) {
    return IntStream.rangeClosed(2, (int) Math.sqrt(n)) 
            .noneMatch(i -> n % i == 0);
}

Кроме того, мы можем улучшить ваш первый пример, обрабатывая 2 как особый случай.Это позволяет начинать с трех и увеличивать на два, пропуская все четные значения.

static boolean isPrime(int n) {
    if (n == 2) {
        return true;
    } else if (n % 2 == 0) {
        return false;
    }
    for (int i = 3; i * i <= n; i += 2) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}
0 голосов
/ 24 декабря 2018

Какой смысл использовать потоки Java8 для достижения этой цели.Для меня вы изобретаете велосипед.Этого одного лайнера будет достаточно.

BigInteger.valueOf(n).isProbablePrime(50);

Также обратите внимание, что есть некоторые проблемы, которые можно лучше решить с помощью потоков.Но это не значит, что поток - это серебряная пуля для решения всех ваших проблем.

Вот выдержка из Документации об определенности.

Для большого известного простого числа и для любой уверенности> 0, верно ли сказать, что b.isProbablePrime (уверенность) всегда будет возвращать true.

0 голосов
/ 23 декабря 2018

Вы должны использовать IntStream.noneMatch там как:

boolean isPrimeStream(int n) {
    return IntStream.range(2, n) // note  division by zero possible in your attempt
                    .noneMatch(i -> n % i == 0);
}

Редактировать : как указано в комментариях Андреаса, используя range(2, n), чтобы избежать деления на ноль, а поскольку деление на 1 всегда приводит к тому, что условие истинно, и возвращает результат как false в противном случае.

Возвращает, нет элементов этого потока соответствует предоставленному предикату

Ваш текущий код использует IntStream.anyMatch

Возвращает ли любые элементы этого потока соответствуют предоставленному предикату

, поэтому он будет возвращать true, если указанное условие удовлетворяется для любого входа, а не когда методдолжен возвращать false.


как сделать аналогично циклу выше

С или выше вы можетеиспользуйте IntStrem.iterate как

private boolean isPrimeStream(int n) {
    return IntStream.iterate(2, i -> i * i <= n, i -> i + 1) // similar to the loop
                    .noneMatch(i -> n % i == 0);
}
...