我想创建一个程序,将所有素数写入文件中(我知道有一个流行的算法“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;
}
答案 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
。我认为你的算法实现中缺少一些东西。您是否有指向您尝试实施的算法的描述的链接?或者这是你开发的算法? (抱歉,我不理解您添加到问题中的算法描述)