【问题标题】:Eratosthenes sieve without multiply, divide, nor `for` loops没有乘法、除法和“for”循环的埃拉托色尼筛子
【发布时间】:2019-04-21 12:34:53
【问题描述】:

我和我的朋友正在做一个大学家庭作业,以制作一个没有任何乘法、除法和for 循环的 Eratosthenes-sieve。 问题是我在教授告诉我们不要使用这些东西之前写了它,现在我不知道该怎么做。 将for 循环更改为while 循环没什么大不了的,但我不知道如何摆脱代码末尾的最后一个乘法。

我的朋友做了一些我不明白的更改(我会评论他所做的更改),如果有人可以向我解释解释,我将非常感激。总结:

  1. 我们需要去掉 for 循环并用 while 循环替换它们

  2. 去掉代码末尾的乘法,这是我的主要问题。

  3. 帮助了解 cmets 中记录的更改。

我们的代码:

import java.util.Scanner;
public class primesieb {

    public static void main(String[] args) {
        //so we declare values and used the scanner to make an input.
        int input = 0;
        Scanner in = new Scanner(System.in);

        System.out.println("give an int bigger that 1:  ");
        input = in.nextInt();

        while (input <= 1)
        {
         //in case the number is smaller than 1.
                System.out.println("the Int must be bigger than 1!.");
                System.out.println("write an Int bigger than 1: ");
                input = in.nextInt(); 
        }
        in.close();
        //now first i wrote it without "+1" but my friend changed it to +1
           boolean[] x = new boolean[input + 1];
        //here I just wanted to add this to set that the position 0 in the string is not a prime number but after thinking I don't see its necessary

               x[0]=false;

        //he did write this commented for loop to assume that all of them are false but for me, it doesn't make sense, pls explain if it's necessary.
        //for (int i = 2; i < x.length; i++) {
          //  x[i] = false;}

        for (int i = 2; i < x.length; i++) {

            while (x[i]) 
            {
                i++;
            }
         // here how can we get rid of the multiplication.
        //the next for loop and if my friend did and a better explain would be nice helping me to represent my code better.
        for (int j = i; j*i < input; j++) 
            {
                x[i * j] = true;
            }
            if (! x[i] && i < input) 
            {
                System.out.println("the number" + i + "is prime. ");
            }
        }
    }       
}

我们在 Eclipse 上测试了这段代码,它可以工作,但我们需要避免使用乘法。

【问题讨论】:

  • 提示:X、2X、3X等序列与X、X+X、(X+X)+X...
  • @RealSkeptic。你说的是这部分吧??? for (int j = i; j*i 我完全同意这在数学上是 1000% 正确的,但我不知道如何在代码中引入它。对不起,但我的大脑仍然没有得到整个编码逻辑。我是初学者,恐怕我不得不请你向我解释如何用java编写它。感谢您尝试帮助我,我很感激。
  • 我现在尝试使用 (int)Math.sqrt(i),但在 primesiebselber.main(primesiebselber.java: 31) 我不知道这是什么。我确实尝试过 (int j = i, z= (int)Math.pow (i,j); z

标签: java primes sieve-of-eratosthenes


【解决方案1】:

首先,让我们简化您的数字输入:

    Scanner in = new Scanner(System.in);

    int input = 0;

    while (input <= 1) {
        System.out.println("Give an int bigger than 1: ");
        input = in.nextInt();

        if (input <= 1) {
            System.out.println("The int must be bigger than 1!.");
        }
    }

    in.close();

尽量减少空间使用,你的朋友说的不对:

//now first i wrote it without "+1" but my friend changed it to +1
boolean[] x = new boolean[input + 1];

x[0]=false;

由于您只打印小于 input 的素数(即使 input 是素数)并且您跳过了 0 和 1,您可以缩短 x 三个元素:

boolean x[] = new boolean[input - 2];  // all initialized to false

任何for 循环始终可以展开到while 循环:

for (int i = 2; i < x.length; i++) {

for 循环设置中的三个分号分隔的元素中,第一个出现在while 循环之前,第二个是while 循环条件,第三个是while 中的最后一个语句循环:

int i = 2;

while (i < input) {  // 'input' instead of 'x.length' in our new design

    // (the rest of the code that follows below goes here)

    i++;
}

这是一个潜在的问题:

while (x[i]) 
{
    i++;
}

因为在下一个x[i] 之前对i 没有边界检查。由于x 中分配了额外的未使用空间,这对您很有效。现在我们需要更精确:

while (x[i - 2]) {
    if (++i >= input) {
        break outer;
    }
}

我们正在使用i - 2,因为我们正在跳过缺少的 0 和 1 条目。我们使用break outer; 而不仅仅是break;,因为我们需要退出包含while 循环的while 循环。所以回去改:

while (i < input) {

以上改为:

 outer: while (i < input) {

这个for 循环的转换有些不同,因为它不需要乘法:

for (int j = i; j*i < input; j++) {
    x[i * j] = true;
}

我们将重复添加i,而不是乘以i。一开始效率稍低,但其他方面都很好:

int j = i + i;

while (j < input) {
    x[j - 2] = true;
    j += i;
}

不需要此测试:

if (! x[i] && i < input)

我们已经知道x[i]falsei &lt; input 从我们上面的工作。因此,只需完成:

System.out.println("The number " + i + " is prime.");

i++;  // we added this earlier to finish off our first 'for' to 'while' conversion

如果您仔细遵循这些更改,您现在应该有一个没有for 循环、没有乘法和没有浪费的数组元素的工作程序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多