简体   繁体   English

为什么此质检程序起作用,而如果我尝试使其更高效则不起作用

[英]Why does this prime checker work, and not work if I try to make it more efficient

Below is one of the first programs I made (with help from the Internet) in Java. 下面是我用Java编写的第一个程序(在Internet的帮助下)。 It is a program that checks if a given integer is prime or not and prompts the user with feedback. 它是一个程序,用于检查给定的整数是否为质数,并提示用户反馈。 If the user input is not an integer it outputs that it is not an integer. 如果用户输入的不是整数,则输出的不是整数。 The latter also happens when Big Integers are entered. 输入大整数时也会发生后者。 This is the code: 这是代码:

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!");
        }

    }
}

This program does his job, but I do not know why the part with the if-statement works. 该程序可以完成他的工作,但是我不知道为什么带有if语句的部分起作用。 How is it possible that "i == number" gives a value of true (it prints out "YES! PRIME" when you enter a prime)? “ i ==数字”的值如何可能为true (输入质数时会打印出“ YES!PRIME”)? The local variable i gets incremented in the for-loop, but the if-statement is outside of the for-loop. 局部变量i在for循环中递增,但是if语句在for循环之外。

/edit the paragraph below is nonsense as Jim Lewis points out /编辑 ,正如吉姆·刘易斯Jim Lewis)指出的那样,下面的段落是胡说八道
Thinking about it now, the only reason I can think of that this is the case is because the == operator checks if the i-'object' and number-'object' belong to the same 'type' (ie, have a reference to the same object). 现在考虑一下,我能想到的唯一原因是因为==运算符检查i-'object'和number-'object'是否属于相同的'type'(即具有引用)到同一对象)。 Since they both belong to the type of primitive integers this program catches the integers (other input throws a NumberFormatException which is caught and outputs "Not an integer"). 由于它们都属于原始整数的类型,因此该程序将捕获整数(其他输入将引发NumberFormatException,该数字将被捕获并输出“非整数”)。 The ones that are primes pass the first for-loop and then the magical if-statement gives "true" and it prints out "YES! PRIME!". 质数的那些传递第一个for循环,然后神奇的if语句给出“ true”,并输出“ YES!PRIME!”。

Am I on the right track? 我在正确的轨道上吗?

I have improved this program by removing the magical if-statement and changing it for an if-else-statement like this: ( /edit fixed problem with code thanks to answer of ajb ) 我通过删除神奇的if语句并将其更改为if-else语句,从而改进了该程序:( / edit 修复了代码问题,感谢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!");

By only going up to the square root of the input number the calculation time improves (I know it can be even more improved by only checking odd numbers or using a AKS Primality Test , but that is beside the point). 通过仅增加到输入数字的平方根,计算时间得到了改善(我知道,仅检查奇数或使用AKS Primality Test甚至可以进一步改善计算时间,但这并不重要)。

My main question is why I could not improve the efficiency of the first program (with the magical if-statement) in the same manner. 我的主要问题是为什么我不能以相同的方式提高第一个程序的效率(使用神奇的if语句)。 When I enhance the for-loop like this "(i = 2; i < Math.sqrt(number) + 1; i++)" in the first program it does no longer print out "YES! PRIME!" 当我在第一个程序中像这样的for循环增强“(i = 2; i <Math.sqrt(number)+ 1; i ++)”时,它不再打印“ YES!PRIME!”。 when you input a prime. 输入素数时。 It gives a blank. 它给出了一个空白。 Even if my previous explanation is correct - which it is probably not - this is not explained. 即使我先前的解释是正确的-可能不是-也没有解释。

You may enlighten me. 您可以启发我。

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 . 解答: int i在for循环范围之外,并且经过多次for循环直至达到数值,当我们确定它是质数时,i的值将达到数值number Furthermore, after checking the disappearing "YES! PRIME!" 此外,在检查消失的“是!头等!”之后 statement once again it turns out it is actually possible to change number in both the if-statement and for-loop to ( Math.sqrt(number) + 1 ) and have working code. 语句再次证明实际上可以将if语句和for循环中的数字都更改为(Math.sqrt(number)+ 1)并具有有效的代码。 So the question was based on a false premise. 因此,问题是基于错误的前提。

i is declared outside the for loops, so its value is still in scope and available after the loop finishes (nothing to do with comparing data types or anything like that!). ifor循环之外声明,所以它的值仍然在范围内,并且在循环结束后才可用(与比较数据类型或类似内容无关!)。

If no divisors were found, the i < number loop condition will eventually fail, with i == number . 如果未找到除数,则i < number循环条件最终将失败,且i == number (If the loop finds a divisor and hits the break statement, that condition no longer holds). (如果循环找到除数并命中break语句,则该条件不再成立)。

When you do the sqrt optimization, the end condition of the loop is changed, so i == number no longer holds after the loop exits, even if the number is prime. 当您执行sqrt优化时,循环的结束条件将发生更改,因此即使循环数是质i == numberi == number在循环退出后也不再成立。

In my opinion it would be more clear to explicitly set a flag (eg isPrime=0 just before breaking out of the loop), then check that flag rather than looking at the loop variable to see whether the loop completed or not. 在我看来,更明确地明确设置一个标志(例如,在退出循环之前isPrime=0 ),然后检查该标志,而不是查看循环变量以查看循环是否完成。

// I do not understand why the if-statement below works //我不明白下面的if语句为什么起作用

Explanation: Because i has been incremented until it equals number. 说明:因为我一直递增,直到等于数字。 If you stop at sqrt(number) then the if statement will always fail. 如果在sqrt(number)停止,则if语句将始终失败。

By the way I don't like using square root with integers. 顺便说一句,我不喜欢使用整数的平方根。 I like this better for a isPrime function: 我更喜欢使用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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM