【问题标题】:About Prime Generation in "C" - What is wrong with my code ? -关于“C”中的 Prime Generation - 我的代码有什么问题? -
【发布时间】:2011-01-06 22:27:26
【问题描述】:

我是一名三年级的非正规 CS 学生,我刚刚意识到我必须开始编码。

我以较低的成绩通过了我的编码课程,因此我没有良好的编码和编程背景。

我正在尝试编写一个在给定上限和下限之间生成素数的代码。不太懂C,强制我写个粗略的代码,然后再去解决。我可以轻松设置预期功能的逻辑,但我可能通过几种不同的方式创建了错误的算法。

在这里我分享我的最后一个代码,我打算计算当一个数字给出余数时,它应该是 self 和 1 ,所以 count==2;我的实现和我的解决方案生成风格有什么问题?希望你能温暖我的编程世界,我找不到足够的动力和勇气深入编程。

包含 Stdio 和 Math.h

int primegen(int down,int up)
{   
    int divisor,candidate,count=0,k;

    for(candidate=down;candidate<=up;candidate++)
    {
        for(divisor=1;divisor<=candidate;divisor++)
        {
            k=(candidate%divisor);
        }
        if (k==0) count++;
        if(count==2)
        {
            printf("%d\n", candidate);
            count=0;
        }
        else
        {
            continue;
        }
    }
}

int main()
{
    primegen(3,15);
    return 0;
}

【问题讨论】:

  • third year CS student and i have to start coding 什么?
  • @Falmarri - 绝对是 WTF 时刻。 :-)
  • @alorsoncode,如果需要鼓励你编写代码,那么也许你应该重新考虑你的职业。例如,我的女朋友觉得我需要劝阻不要写代码。
  • “我找不到足够的动力和勇气来深入编程” - 一般来说,计算机科学包含很多编程。此外,它需要大量的自我激励来学习,大量的自学;随着不断变化的技术世界不断适应,作为计算机科学家的您也必须适应。我并不是说您无论如何都在错误的领域,但我是说,如果您要留在计算机科学领域,您需要习惯编程并激励自己不断学习更多有关编程的知识。祝你好运!
  • 嘿 - 让我想起了我的一位老派教授(在不止一个方面),他认为计算机科学是数学的一个分支,编写实际程序属于电气工程学科,而不是玷污他的教学大纲。

标签: c math computer-science


【解决方案1】:

您在 candidate%divisor 测试中包含 1 和 candidate,这两者都将始终返回 0,因此您测试的每个数字都将显示为素数。

而不是这个:

for(divisor=1;divisor<=candidate;divisor++)

这样做:

for(divisor=2;divisor<candidate;divisor++)

更新

您的代码有太多问题无法列出,但还是有几个:

  • 您在 for 循环外检查 candidate%divisor 的结果
  • 到您检查 k 时,k 始终为 candidate%candidate,或 0
  • 你只检查一次k,在除数循环之后
  • 不要在循环结束时continue,这是默认情况下发生的情况

看,这里有一些最简单的实现的伪代码。尝试找出您的代码与此不同的地方:

for candidate = down to up
  // assume the candidate is primt
  prime = true

  // check all divisors from 2 to the candidate - 1, inclusive
  for divisor = 2 to candidate - 1
    if candidate % divisor == 0
      // divisor is a factor of candidate
      // candidate isn't prime, so we can stop checking
      prime = false
      break
    end if
  next divisor

  // if prime is still true, we successfully tested every number from 2..candidate
  // and found no factors
  if prime
    print "candidate {candidate} is prime!"
  end if
next candidate

【讨论】:

  • 感谢您的伪代码,您的第一个建议对执行没有影响。 :(如果你扩展你对“for”循环的提议,我希望我能很容易理解。对不起,充当假人:)
【解决方案2】:
  • 在您的内部循环中,您计算​​所有除数的candidate%divisor,但只有在循环完成后,您才检查是否应增加count。因此,对于检查的最后一个除数,您只需为每个候选者增加一次。
  • 您也不要为外部循环中的每个候选者重置count。因此,您可以将所有候选人的找到的除数一起计算,而您想单独计算每个候选人的除数。

【讨论】:

  • 我现在意识到了;例如 6 个代码尝试 1,2 然后 count==2 以便将 6 视为素数。我试图克服这个问题,但我忘记了很多 C 来解决这些问题。我一直在努力。感谢您的回答。
【解决方案3】:
#include <stdio.h>
#include <math.h>

int primegen(unsigned int down,unsigned int up)
{   
int *ar;
int divisor,candidate,count=0,k;

for(candidate=up;candidate>=down;candidate--)
    {   count=0; 
        for(divisor=2;divisor<candidate;divisor++)
            {if (((candidate%divisor)==0)) count++; }
            if(count==0) {printf("%d\n",candidate); count=0;}

    }
}
int main()
{
primegen(3,15);
return 0;
}

最后我纠正了我的解决方案。主要问题是我没有在第二个 for 循环之前将 count 分配为零。我更改了候选的顺序(从大到小),并纠正了一些语法错误。

感谢大家鼓励的帮助和回答。 :) 我很高兴完成了这项工作,因此我可以解决其他算法和问题。

【讨论】:

    【解决方案4】:

    需要记住的一些提示

    if(!(candidate & 0x01))
        // We know its even so we can stop
    
    if(candidate == potential_factor)
        // We can stop
    
    if(candidate % potential_factor == 0)
        // The potential factor IS a factor and we can stop
    

    【讨论】:

    • 感谢您的回复,但我不知道第一个符号?为什么是十六进制?
    • 我认为,首先条件是检查均匀度,然后是 2k,因此它不能是素数。我是对的(正确理解吗?)
    • 它检查“one's bit”是否未设置。如果你没有 2^0,你只能是偶数。
    【解决方案5】:

    为了清晰起见,有人重新格式化了原始提交表单中的代码。在此过程中,他们修改了代码中的三个错误之一。

    第一个错误是第二个 for 语句后面没有括号。结果,循环体仅由第二个 for 语句之后的语句组成。通过阅读代码,很明显提问者打算重复执行第二个循环语句之后的所有内容。这不是发生的事情。

    基本上,这个想法是:对于范围内的每个数字,尝试从 1 到候选者之间的所有数字。数一数划分它的人的数量。看看是否正好有 2。这是一个正确的算法,不除以 2 的答案是错误的。

    但是,实现是这样做的:对于范围内的每个数字,将候选除以 1 和候选之间的每个数字。然后,一旦你完成了所有的除法,检查最后一个是否是偶数,如果是,则将计数加 1。所以,发生的事情是,您实际上只是在检查 candidate % candidate == 0 是否总是如此。

    第二个错误是计数只有在达到 2 时才会重置。所以,发生的情况是,对于任何输入,代码都会返回每隔一个数字。对于每个候选人,count++ 只发生一次。所以它达到 2 并每隔一段时间重置一次。

    第三个错误是一旦最里面的循环被修复了,那么 continue 就会做错事,因为它只继续最里面的循环。

    【讨论】:

    • 感谢您认真分析代码,我正在努力减少语法错误。
    【解决方案6】:

    我知道您的代码仅用于教育目的,但是您应该考虑使用埃拉托色尼筛法,因为它可能是解决您问题的最快算法。它的基本作用是:

    1. 首先考虑所有数字素数。
    2. 从 2 开始,将素数的所有倍数视为非素数。
    3. 转到下一个质数并使其所有倍数都不是质数。

    我认为您可以通过阅读以下内容更好地理解该算法: http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes

    至于实现,只需使用一个将所有元​​素设置为零的数组,并将素数到素数的元素设置为一。

    希望这会有所帮助!

    【讨论】:

    • 这已经超出了我的预期,这是一个很好的算法,所以当我第一个算法成功时,我会深入研究你的方法。
    • 顺便说一句,我只是尝试习惯编写基本算法来热身 C 编程。今天之前写了很多不同的代码,但是练习不足,忘记了很多...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-02
    • 1970-01-01
    • 2015-06-26
    • 1970-01-01
    • 1970-01-01
    • 2013-02-11
    相关资源
    最近更新 更多