为什么这个主要检查器工作,如果我试图提高效率,则不起作用

时间:2013-08-22 22:24:29

标签: java primes math.sqrt

以下是我在Java中制作的第一个程序(在互联网的帮助下)。它是一个程序,用于检查给定的整数是否为素数,并提示用户提供反馈。如果用户输入不是整数,则输出它不是整数。后者也会在输入Big Integers时发生。这是代码:

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语句的部分有效。 “i == number”如何给出真值(当你输入素数时它打印出“YES!PRIME”)?局部变量i在for循环中递增,但if语句在for循环之外。

/ edit 下面的段落是无意义的Jim Lewis points out
现在想一想,我能想到的唯一原因就是这种情况是因为==运算符检查i-'object'和number-'object'是否属于同一'type'(即,引用同一个对象)。由于它们都属于原始整数的类型,因此该程序捕获整数(其他输入抛出一个NumberFormatException,它被捕获并输出“Not an integer”)。那些素数通过第一个for-loop,然后神奇的if语句给出“true”,它打印出“YES!PRIME!”。

我是在正确的轨道上吗?

我通过删除神奇的if语句并将其更改为if-else语句来改进此程序,如下所示:( / edit 修复了问题代码感谢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循环“(i = 2; i&lt; Math.sqrt(number)+ 1; i ++)”时,它不再打印出“YES!PRIME!”当你输入素数时。它给出了一个空白。即使我之前的解释是正确的 - 它可能不是 - 这没有解释。

你可以启发我。

答案: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。此外,在检查消失的“是!PRIME!”之后声明再一次证明它实际上可以将if语句和for循环中的数字改为(Math.sqrt(number)+ 1)并且具有工作代码。所以问题是基于错误的前提。

2 个答案:

答案 0 :(得分:2)

ifor循环之外声明,因此它的值仍然在范围内并且在循环之后可用 完成(与比较数据类型或类似的东西无关!)。

如果没有找到除数,最终将i < number循环条件 失败,i == number。 (如果循环找到一个除数并点击break语句, 那个条件不再成立。)

执行sqrt优化时,循环的结束条件会发生变化, 所以i == number在循环退出后不再成立,即使数字是素数。

在我看来,明确设置一个标志(例如isPrime=0)会更清楚 在打破循环之前),然后检查该标志而不是查看 循环变量,以查看循环是否完成。

答案 1 :(得分:1)

  

//我不明白为什么下面的if语句起作用

说明:因为我已经增加,直到它等于数字。如果你停在sqrt(数字),那么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;