为什么这段代码不能正常工作?

时间:2010-04-14 00:06:35

标签: c++ binary primes

我想创建一个程序,将所有素数写入文件中(我知道有一个流行的算法“Sieve of Eratosthenes”,但我试图自己制作)。我正在尝试消除仍然具有值1的字节的所有复杂性,然后将它们写入文件中。

#include <iostream>
#include <stdlib.h>  
#include <stdio.h>

void afficher_sur_un_ficher (FILE* ficher, int nb_bit);
char el_mask (int x);

int main()
{
    FILE* p_fich;
    char tab[4096], mask, eli_mask;
    int nb_bit = 0, x, f;

    for (int i = 0; i < 4096; i++)
    {
        tab[i] = 0xff;
    }

    for (int i = 0; i < 4096; i++)
    {
        for (mask = 0x01; mask != 0; mask <<= 1)
        {
            if ((tab[i] & mask) != 0)
            {
                x = nb_bit; 
                while ((x > 1) && (x < 16384))
                {
                    eli_mask = el_mask (x);
                    f = x / 8;
                    tab[f] = tab[f] ^ eli_mask;
                    x = x + nb_bit;
                }
                afficher_sur_un_ficher (p_fich, nb_bit);
            }
            nb_bit++;
        }
    }
    system ("PAUSE");
    return 0;
}

void afficher_sur_un_ficher (FILE* ficher, int nb_bit)
{
    ficher = fopen ("res.txt", "a+");
    fprintf (ficher, "%d \t", nb_bit);
    int static z;
    z = z + 1;
    if (z % 10 == 0)
        fprintf (ficher, "\n");
    fclose (ficher);
}

char el_mask (int x)
{
    x = x % 8;
    switch (x)
    {
        case 0:
            x = 0b00000001;
        break;
        case 1:
            x = 0b00000010;
        break;
        case 2:
            x = 0b00000100;
        break;
        case 3:
            x = 0b00001000;
        break;
        case 4:
            x = 0b00010000;
        break;
        case 5 :
            x = 0b00100000;
        break;
        case 6 :
            x = 0b01000000;
        break;
        case 7:
            x = 0b10000000;
        break;
    }
    return x;
}

3 个答案:

答案 0 :(得分:5)

循环中似乎存在一个问题,即试图清除指示非素数的位:

while (( x > 1 )&&(x < 16384))
{
    tab[i] = tab[i] ^ mask ;
    x = x * 2 ;
}

由于i在此循环中没有改变,因此在递增x时,您基本上会关闭和打开相同的位。除了将索引修复为tab[]之外,您可能希望将操作从xor(^)更改为无条件清除该位的操作 - 一旦清除该位,您不需要处理那个位再次用于“重置”该位的不同因素。请注意,i的简单递增不会,因为x的其他元素中tab的倍数可能不在同一位偏移中(实际上,{{1}的单个元素可能包含几个tab[]}的倍数。

即使您解决了这个问题,我认为循环可能没有按照您的预期进行,因为x不会通过其倍数走x = x * 2; - 您最终会跳过一些非素数。

关于'Eratosthenes的筛子'如何起作用的一些研究可能有所帮助。

答案 1 :(得分:1)

也许我错过了一些东西,但这看起来很不稳定。我不记得常见的素数算法,但是,例如,

(excerpts) tab[i] = 0xff ; mask = 0x01 ;

for (int j = 0 ; j < 8 ; j++) { if ((tab[i] & mask) != 0 ) mask = mask<<1 ;

这意味着你总是会去8次 - 所以为什么要检查'&amp;'?

另一个,

x = nb_bit ; while (( x > 1 )&&(x < 16384)) { tab[i] = tab[i] ^ mask ; x = x * 2 ; }

这只是在每次迭代时翻转位。这就是你想要的吗?

最后,因为我不知道你的意思,所以要小心对象的位长。你可能会翻转

<00> 0000 0000 1111 1111 ^ 0000 0001

1111 1111 1111 1111 ^ 0000 00001

由于我不太明白你想做什么,不确定这可能是相关的。

编辑(在Hamza的评论之后):

是。这个循环的作用如下 - 比较/'和'

1111 1111 1111 1111

      0000 0001
      0000 0010
      0000 0100,

并且总是如此。我不知道你想在这里做什么,但这看起来很可疑(现在改变位置暂时没有互联网,但是gl。:))。

答案 2 :(得分:1)

您可以稍微简化一下主要功能:

int main (int argc, char** argv) {
    FILE* p_fich;
    char tab[4096] , mask;
    int nb_bit = 0 , x;

    memset(tab, 0xFF, 4096);
    for (int i = 0; i < 4096; i++) {
        for (mask = 0x01; mask != 0; mask <<= 1) {
            if ((tab[i] & mask) != 0) {
                for (x = nb_bit; (x > 1) && (x < 0x4000), x<<=1)
                    tab[i] ^= mask;
                afficher_sur_un_ficher (p_fich, nb_bit);
            }
            nb_bit++;
        }
    }
    system ("PAUSE");
    return 0;
}

现在,要解决您的问题: 您的afficher_sur_un_ficher函数将打印传递给它的任何内容,并且在((tab[i] & mask) != 0)为真的每个循环迭代中调用该函数。由于您将每个tab[i]字节初始化为0xFF,因此屏蔽任何给定的位组合始终会导致if语句评估true。您正在改变tab[i]的值,但是一旦这样做,您就不再使用该位,因此它不会改变始终采用if语句的事实。这就是您看到每个条目都被记录的原因。

修改 如果您简化了所有不影响输出决策或输出值的代码,最终会得到以下结果:

memset(tab, 0xFF, 4096);
for (int i = 0; i < 4096; i++) {
    for (mask = 0x01; mask != 0; mask <<= 1) {
        afficher_sur_un_ficher (p_fich, nb_bit);
        nb_bit++;
    }
}

如您所见,此代码将打印一个递增的整数序列(0到(4096 * 8)-1),并且完全独立于tab数组和{{1}的特定值}和i。我认为你的算法实现中缺少一些东西。您是否有指向您尝试实施的算法的描述的链接?或者这是你开发的算法? (抱歉,我不理解您添加到问题中的算法描述)