是否可以使C代码更小?它打印出从0到1000的所有素数。
C,89个字符
int i,p,c;for(i=2;i<1e3;i++){c=0;for(p=2;p<i;p++)if(i%p==0)c++;if(c==0)printf("%u\n",i);}
是否可以使C代码更小?它打印出从0到1000的所有素数。
C,89个字符
int i,p,c;for(i=2;i<1e3;i++){c=0;for(p=2;p<i;p++)if(i%p==0)c++;if(c==0)printf("%u\n",i);}
Answers:
(我写这篇文章并没有意识到C语言中整数的大小限制,因此对于缩短代码实际上没有用。)
首先,谈一谈算法。在编写代码之前,您应该考虑最好的整体策略来获得结果。
你做审判庭检查素性-测试每个潜在除数p
的i
。以字符为单位的代价很高,因为它需要两个循环。因此,无循环地测试素数可能节省字符。
通常更短的方法是使用威尔逊定理:n
当且仅当该数为质数
fact(n-1)%n == n-1
fact
阶乘函数在哪里。由于您正在测试n
从1
到的所有可能的情况1000
,因此可以通过跟踪正在运行的产品P
并P*=n
在每个循环之后进行更新来避免实施阶乘。这是此策略的Python实现,可打印最多一百万个素数。
另外,您的程序只需要达到1000个就可以打开另一个策略:Fermat素数测试。对于某些人来说a
,每个总理都n
可以满足
pow(a,n-1)%n == 1
不幸的是,有些复合材料n
也通过了这一测试a
。这些称为Fermat伪素数。但是,a=2
并且a=3
不要在一起直到都失败n=1105
,所以它们足以满足您检查质数直到1000的目的。(如果1000代替100,则只能使用a=2
。)因此,我们使用(非在线代码)检查素数
pow(2,n-1)%n == 1 and pow(3,n-1)%n == 1
这也无法识别素数2和3,因此需要特例。
这些方法是否更短?我不知道,因为我不使用C语言编写代码。但是,它们是您在尝试编写一段代码开始计算字符之前应该尝试的想法。
int
s是32位的。费马公司也是如此。
fact(int n, int m) { return (n==0) ? 1 : (n*f(n-1)) % m; }
话,即使是相当大的值,结果也不会溢出32位整数n
。(m
是模数)
(n*fact(n-1,m)) % m
。这就突出了问题:您无法避免实现的递归,fact
因为m
外循环的每次迭代都会有所不同。
受Alchymist解决方案启发:
int i=1,p;for(;i++<1e3;p-i||printf("%d\n",i)){p=1;while(i%++p);}