我在编写一个找到2-50之间的素数的程序时遇到了麻烦。我的程序现在找到“大多数”素数,但包括一些非素数。我知道有更多有效的方法和策略可以找到素数,但我在尝试更有效和更有效的策略之前,首先要尝试各种可能性。现在编写程序的方式,如果它确实找到一个素数,它会多次打印它,而我只想打印一次。我的程序在概念上是正确的还是我的理由存在缺陷。为什么我的程序主要找到素数但是抛出一些非素数?为什么我的程序多次打印素数?
以下是我解决问题的方法。
创建一个for循环来表示2-50之间的潜在素数。用变量“i”表示这些潜在的素数。此循环将从50开始倒计时。
由于只有在除了自身和1之外没有其他可分数的情况下,数字才是素数,我想创建一个内部for循环,将i除以2和i -1之间的每个可能数,以查看是否有任何这些数字均匀分为i。用变量j表示这些可能的除数。如果在任何时候j确实均分为i,那么它不是素数,所以我希望我的内循环退出。
如果我被j的所有数字除以并且没有数字均匀分配到i那么该数字如果是素数并且想要打印该数字。
*
import acm.program.*;
public class PrimeNumber extends ConsoleProgram{
public void run(){
for (int i =50; i >= 2; i--){
for (int j= 2; j < i-1; j++){
if (i % j >= 1){
println(i);
}else{
if (i % j == 0) break;
}
} /*end of inner loop */
} /* end of for loop */
} /* end of run method */
}
答案 0 :(得分:2)
你犯了2个错误。第一个问题在@Thomas的评论中进行了解释,第二个问题在@rolfl的评论中进行了解释。我在这里纠正了他们:
public class PrimeNumber extends ConsoleProgram {
public void run() {
for (int i = 50; i >= 2; i--) {
boolean isPrime = true;
for (int j = 2; j < i-1; j++) { //increment "j" not "i"
if (i % j == 0) {
isPrime = false;
break;
}
}
if (isPrime) System.out.println(i);
}
}
}
注意:我使用此代码验证了解决方案(在IDE中保存为PrimeNumber.java):
public class PrimeNumber {
public static void main (String args[]) {
for (int i = 50; i >= 2; i--) {
boolean isPrime = true;
for (int j = 2; j < i-1; j++) { //increment "j" not "i"
if (i % j == 0) {
isPrime = false;
break;
}
}
if (isPrime) System.out.println(i);
}
}
}
编辑:为了您的理解,您的主要问题是这里的逻辑:
for (int j= 2; j < i-1; j++) {
if (i % j >= 1) {
println(i);
仅在检查一种可能性后打印i
。
例如,取i = 7
。您必须先对i % j
= 6,5,4,3和2进行j
测试,然后才能说i
为素数。正如您所做的那样,您不能只为i % j
测试j = 6
。为此,您的println
语句应该在for循环之后,而不是嵌套在其中,因此您可以首先测试j
的所有可能值。
编辑2:以回应
巧合的是,赋值的第一部分是编写一个谓词方法,如果数字是素数则返回true,如果不是使用蛮力策略则不是素数。任务的第二部分是找到一种更有效的方法,并重新完成任务的第一部分,以提高效率。我试图使用两个for循环来解决问题,看看我是否可以做到这一点。可以用两个没有标签的for循环完成,并继续,因为我的书尚未涉及到吗?
尝试这样的事情:
public boolean isPrime(int number) {
for (int i = 2; i < number; i++) {
if (number % i == 0) {
return false; //not prime
}
}
return true; //prime
}
答案 1 :(得分:1)
您正确地注意到,如果数字i
可以平均分为数字j
,那么i % j == 0
。
但是,每当您发现i % j >= 0
的情况时,您就会打印我 - 这并不意味着i
是素数,因为可能还有其他j
i
可以平均分为。
相反,您应首先浏览所有j
,并且只有在没有人提供== 0
的情况下,您才应该考虑i
素数。您可以使用最初为isPrime
的布尔变量true
,但是一旦找到false
j
,内部for循环就会设置为i
{{1}}可以均分。
答案 2 :(得分:1)
第二个循环(内循环)中存在错误。
你应该递增j
而不是i
....即内在循环应该是
for (int j= 2; j < i-1; j++){
而不是
for (int j= 2; j < i-1; i++){
答案 3 :(得分:0)
这个if语句:
if (i % j >= 1){
println(i);
将打印未除以j编号的每个数字,并且您要打印的数字不是那些从一个减法中得到除以0的除法值的数字,而是用于所有子数。
更快的解决方案是采用潜在质数的布尔数组并像这样循环。
for ( i = 2; i < sqrt(maxvalue); i ++){
for(j = 1; j < sqrt(maxval); j++){
potentialy_prime[i*j]=false
}
}
for (potentialy_prime){
if(potentialy_prime[i]==true)
print(i "is prime")
}
答案 4 :(得分:0)
查看dydx关于这个问题的答案:https://stackoverflow.com/questions/13437162/java-finding-prime-numbers。或者这个问题:Prime number calculation fun或者这个Getting the prime numbers等等......
答案 5 :(得分:0)
您的代码有3个问题:
在内部循环中,您正在增加i
而不是增加j
。
您可以尽快打印该号码i % j >= 1
,但下一个j
可能会划分i
,因此i
不是素数。
你应该在sqrt(i)停止内循环,以避免无用的测试。
以下是代码的更正版本:
OUTER: for (int i = 50; i >= 2; i--) {
for (int j = 2; j <= (int) Math.sqrt(i); j++) {
if (i % j == 0)
continue OUTER;
} /* end of inner loop */
println(i);
} /* end of for loop */
答案 6 :(得分:0)
此代码应打印出素数。初始假设是每个整数&gt; = 2都是素数(在布尔数组中为真)。遍历数组时,如果发现数字为素数,则通过在布尔数组中将它们设置为false来交叉出该数字的倍数(因为它们不是素数)。最后,布尔数组中的数字为true,仅为素数。
时间复杂度:O(n log(log n))
public class PrimesImprovement
{
public static void main(String[] args)
{
System.out.println("Printing primes from 1 to 100");
int i;
int j;
//boolean prime;
boolean[] prime_arr=new boolean[100];
Arrays.fill(prime_arr,true); // Assumption
prime_arr[0]=prime_arr[1]=false; // As 0 and 1 are not prime numbers
for ( i=2;i<prime_arr.length;i++)
{
if(prime_arr[i])
{
for ( j=2;i*j<prime_arr.length;j++)
{
prime_arr[i*j]=false;
}
}
}
for( i=0; i<prime_arr.length; i++)
{
if(prime_arr[i])
{
System.out.print(i+" ");
}
}
System.out.println();
}
}