2013-08-22 2 views
2

Ниже приведена одна из первых программ, которые я сделал (с помощью Интернета) на Java. Это программа, которая проверяет, является ли заданное целое число простым или нет, и запрашивает у пользователя обратную связь. Если пользовательский ввод не является целым числом, он выводит, что он не является целым числом. Последнее также происходит при вводе больших целых чисел. Это код:Почему этот первичный контролер работает, а не работает, если я попытаюсь сделать его более эффективным.

import java.util.Scanner; 

class BasicPrime1 { 
    public static void main(String[] args) { 

     try { 
      System.out.println("Enter an Integer: "); 
      Scanner sc = new Scanner(System.in); 

      int i; 
      int number = Integer.parseInt(sc.nextLine()); 

     // 1 and numbers smaller than 1 are not prime 
      for (i = 1; number <= i;) { 
       System.out.println("NOT a prime!"); 
       break; 
      } 

     // Number is not prime if the remainder of a division (modulus) is 0 
      for (i = 2; i < number; i++) { 
       int n = number % i;   
       if (n == 0) {     
        System.out.println("NOT a prime!"); 
        break; 
       } 
      } 

     // I do not understand why the if-statement below works. 
      if(i == number) { 
       System.out.println("YES! PRIME!"); 
      } 
     } 

     catch(NumberFormatException nfe) { 
      System.out.println("Not an integer!"); 
     } 

    } 
} 

Эта программа выполняет свою работу, но я не знаю, почему работает эта часть с if-statement. Как возможно, что «i == number» дает значение true (он печатает «YES! PRIME» при вводе простого числа)? Локальная переменная i увеличивается в for-loop, но оператор if находится вне цикла for.

/редактировать ниже параграф нонсенс, как Jim Lewis points out
Думая об этом сейчас, единственная причина, я могу думать о том, что это так, потому что проверки оператора ==, если я-`объектно 'и number-'object' относятся к одному и тому же «типу» (т. е. имеют ссылку на один и тот же объект). Поскольку они оба относятся к типу примитивных целых чисел, эта программа ловит целые числа (другой вход генерирует исключение NumberFormatException, которое выдается и выводит «Не целое число»). Те, которые являются штрихами, передают первый цикл for, а затем магическое if-statement дает «true», и он печатает «YES! PRIME!».

Я нахожусь на правильном пути?

Я улучшил эту программу, удалив волшебную если-заявление и изменить его для если-то еще-заявление, как это: (/редактирования исправлена ​​проблема с кодом, благодаря answer of ajb)

boolean factorFound = false;    
for (i = 2; i < Math.sqrt(number) + 1; i++) { 
    int n = number % i; 
    if (n == 0) { 
     factorFound = false; 
     break; 
    } 
    else { 
     factorFound = true; 
    } 
} 
if(factorFound == false) System.out.println("NOT a prime!"); 
if(factorFound == true) System.out.println("YES! PRIME!"); 

Подойдя только к квадратному корню из входного номера, время вычисления улучшается (я знаю, что его можно улучшить даже путем проверки нечетных чисел или использования AKS Primality Test, но это не относится к точке).

Мой главный вопрос: почему я не смог повысить эффективность первой программы (с магическим if-утверждением) таким же образом. Когда я улучшаю for-loop как это »(i = 2; i < Math.sqrt (число) + 1; i ++)" в первой программе он больше не распечатывает "YES! PRIME!" когда вы вводите штрих. Он дает пробел. Даже если мое предыдущее объяснение правильное, чего, вероятно, нет, - это не объясняется.

Вы можете просветить меня.

ANSWER: int i is outside of scope of for-loop and after going through the for-loop multiple times upto number the value of i will reach the value number, when we can be sure it is a prime. Кроме того, после проверки исчезнувшего «ДА! ПРЕМЬЕР!» в очередной раз оказывается, что на самом деле можно изменить число как в if-statement, так и for-loop на (Math.sqrt (number) + 1) и иметь рабочий код. Поэтому вопрос был основан на ложной предпосылке.

+0

Во втором примере вы не позволяете ему проходить весь цикл. Если n равно 0, вы знаете, что это не простое, и вы можете выйти из цикла прямо сейчас, что правильно. Но если n не равно 0, вам нужно снова пройти цикл, но, как вы его закодировали, вы выходите. Вам нужно продолжать проходить цикл, а затем, когда цикл завершен, вы проверяете, уходите ли вы, потому что вы обнаружили, что это не просто, или весь цикл завершен. Лучший способ - определить логическое значение, например 'factorFound'; инициализируйте его значением false, установите его значение true перед разрывом и проверьте его после завершения цикла. – ajb

+0

А вы правы. Если число% i отличное от нуля, это не означает, что нет другого более высокого i, для которого оно равно нулю, и, следовательно, второй пример может давать ложные срабатывания. Я обновил код с помощью boolean, и теперь он работает правильно. –

ответ

1

// Я не понимаю, почему если-заявление ниже работает

Объяснение: Поскольку я был увеличен до тех пор, пока число равно. Если вы остановитесь на sqrt (number), то оператор if всегда будет терпеть неудачу.

Кстати, я не люблю использовать квадратный корень с целыми числами.Мне нравится это лучше для функции IsPrime:

 if (number < 2) return false; 
     if (number > 2 && number % 2 == 0) return false; 
     for (int i = 3; i * i <= number; i = i + 2) 
      if (number % i == 0) return false; 
     return true; 
+0

Спасибо за ваш ответ, и это действительно более чистый и эффективный фрагмент кода. –

2

i объявлена ​​вне for петель, поэтому его значение по-прежнему в области видимости и доступны после цикла отделки (ничего общего с сопоставления типов данных или что-нибудь подобное !).

Если не найдено ни одного делителя, условие петли i < number в конечном итоге закончится , с i == number. (Если цикл находит делитель и попадает в оператор break, это условие больше не выполняется).

Когда вы делаете sqrt оптимизации, конечное условие цикла не изменяется, так после выхода цикла i == number больше не выполняется, даже если число простое.

На мой взгляд, было бы более понятно, явно установить флаг (например, isPrime=0 просто , прежде чем вырваться из петли), а затем проверить этот флаг, а не глядя на переменную в петлевой ли завершен цикл или нет ,

+0

Понятное объяснение спасибо! –