【问题标题】:What is going wrong with the logic?逻辑出了什么问题?
【发布时间】:2011-10-30 23:09:07
【问题描述】:

我正在尝试编写一个实现 Eratosthenes 筛子的素数生成器。但是,它在输出中包含了一些合数(例如 25、49 和其他 5 和 7 的倍数)。

这是我的代码:

/*****
 * To find out prime numbers from 1 to 100 with a different procedure
 * Author:Udit Gupta
 * Date:20/08/2011
 */

#include<stdio.h>

int main() {
    int a[100],i,j,k,n;

    for(i=0;i<=99;i++)
        a[i] = i+1;  /*1 to 100 numbers are entered into array*/

    /*Here te actual logic starts .......*/
    j = 1;
    while ( (a[j] != 0) && (j!=50) ) {
        k = 1;
        n = a[j];

        while( (n * k) < 99) {
            a[j+(n*k)] = 0;
            k++;
        }

        j++;
    }

    /*To print output of the array*/
    for (i=0;i<=99;i++) {
        if ( a[i] != 0)
            printf("\n%d",a[i]);
    }

    return 0;
}

这是输出......

udit@udit-Dabba ~/Desktop/letusc/ch8 $ gcc -o Dd Dd.c -Wall udit@udit-Dabba ~/Desktop/letusc/ch8 $ ./Dd

1 2 3 5 7 11 13 17 19 23 25 29 31 35 37 41 43 47 49 53 55 59 61 65 67 71 73 77 79 83 85 89 91 95 97

【问题讨论】:

  • 1 不是质数,顺便说一句...
  • 您是否尝试过使用调试器
  • 你为什么不尝试调试你的代码来找出答案?
  • @MByD:我认为问题是 1、25、35、49、55、65、77、85、91 和 95。
  • @omri 是的,你是对的......我已经应用了逻辑 acc。如果有人能告诉我我做错了什么,我认为是对的?????

标签: c primes sieve-of-eratosthenes number-theory


【解决方案1】:

提示;看看 5 和 25 发生了什么

google 会告诉你如何使用 gdb - 并不难

a[j + n * k] = 0;

我想你是说

a[n * k] = 0;

【讨论】:

  • j=4 so n=a[4]=5 and then for j=4,4+5*1,4+5*2,etc it will go and will make them zero. 25 is a[24] and 24 = 4+5*4
  • @Udit:尝试观察调试器中发生的情况。
【解决方案2】:

您将结果(将非素数标记为零)存储在与从外部循环中读取数据相同的数组中。

数字 4 被(正确地)标记为非素数,但这会产生终止主循环的副作用(因为 a[j] ==0)。

所以你只处理 n=2 和 n=3。

【讨论】:

    【解决方案3】:

    第一个提示:在调试器中,中断n = a[j]; 行。运行几次迭代。当a[j] == 5 时它会停止吗?

    udit@udit-Dabba ~/Desktop/letusc/ch8 $ gdb ./Dd
    [省略 GDB 序言]
    (gdb) b 主要
    0x100000e63 处的断点 1:文件 Dd.c,第 12 行。
    (gdb) r
    启动程序:/home/udit/Desktop/letusc/ch8/Dd
    共享库的读取符号 +。完毕
    
    断点 1,主 () 在 Dd.c:12
    12 for(i=0;i

    RMS(与 that RMS 无关)GDB tutorial 包含一个关于 watchpoints 的部分,上面的示例会话使用了该部分。

    更多提示可根据您的需要提供。

    【讨论】:

    • 我对编程很陌生,linux也请帮我看看如何在linux机器上调试代码??
    • 最好有指南。试试Linux software debugging with GDB,或者如果这对你不起作用,请搜索网络。短版:gdb *executable* 启动 gdb,b (*function name*|*line number*) 设置断点,r 启动程序运行,c 在断点后继续(直到下一个断点),p *expr* 打印值表达式(例如变量名),s 以单步执行一行。有关命令的更多信息,请参阅GDB Cheat Sheet
    • 它永远不会达到 n = 5。它停止得太早了。
    • 非常感谢..我会尝试调试并在这里弄清楚...它永远不会执行 n=5
    【解决方案4】:
    while (n * k < 99) {
      a[j + n * k] = 0;
      k++;
    }
    

    此代码很危险。你很可能最终得到j + n * k 大于 99,这将覆盖任意内存(或者,严格来说,行为未定义)。最好是安全的:

    #include <assert.h>
    
    ...
    
    while (n * k < 99) {
      int index = j + n * k;
      assert(0 <= index && index < 100);
      a[index] = 0;
      k++;
    }
    

    【讨论】:

    • 另外(或另外),更改条件以检查索引是否在范围内:while (j + n * k &lt; LENGTH(a)),给定LENGTH 的合适定义。
    • @Rudy:断言经常测试“不可能”的场景,以防万一。
    • @outis:嘿,这就是 Udit 自己应该发现的。 ;)
    • @Roland:他不会发现的,因为不是他的循环的问题。
    【解决方案5】:

    问题是循环结束得太快了。如果 a == 3, a[j] == 0 并且循环结束。将主循环更改为:

    for (j = 1; j < 50; j++) 
    {
        k = 1;
        n = a[j];
    
        if (n != 0) 
            while (j + n * k <= 99) 
            {
                a[j + n * k] = 0;
                k++;
            }
    }
    

    【讨论】:

      【解决方案6】:

      老实说,帮自己一个忙,在“gdb 调试器教程”上进行网络搜索。您将获得数百次点击。然后,坐下来享受一些乐趣,学习一个强大的工具,如果你继续学习 C、C++ 或其他十几种计算机语言,你将花费成百上千个小时来使用它。 (我对“有趣”的部分很认真;如果你觉得它不好玩,放弃 CS!)

      同时搜索“ddd 调试器”;这是 gdb 的免费 OSS 图形前端——非常好,恕我直言。

      -k

      【讨论】:

      • 确实,在 gdb 中逐行运行代码很有趣。通常问题线(或线之间的过渡)可能只是“跳出来”在你身上。您可能不会立即知道出了什么问题以及如何解决它;但你可以“感觉到”一些可疑的事情刚刚发生。知道哪里出了问题,可以很容易地开始调查为什么
      猜你喜欢
      • 2011-09-10
      • 2020-10-31
      • 2016-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-01
      相关资源
      最近更新 更多