擂台:计算大数阶乘,看看谁的代码最短

liangbch 2008-11-11 07:37:06
前段时间发了一个 "4行代码(170个字符)计算10000以内的阶乘"(http://topic.csdn.net/u/20081107/12/bbe2be15-2a95-48ef-80db-21cd756ee7c9.html),招致板砖无数,好多人都把注意力集中在代码的编写风格上,而几乎没有人探讨如何压缩代码的技巧。
这次重发此帖,希望将注意力集中在探讨压缩代码的技巧上,对优秀的回复,高分赠送,必要时开新贴赠分。

先贴出我的2个版本。

版本1:采用万进制,在主流编译器可以实现1-10000的阶乘,扣除#include 和 #define语句,共167个字节。

#define N 10 //计算N的阶乘,修改N的定义可计算10000以内任意数的阶乘
int a[N]={1},n=N,i,c,m;void main(){
for(;n>1;(a[i]=c)>0?m++:0,n--)
for(c=i=0;i<=m;i++)a[i]=(c+=a[i]*n)%10000,c/=10000;
for(printf("%d",a[m]);--m>=0;)printf("%04d",a[m]);}


版本2:采用10进制,在主流编译器可以实现1-200000的阶乘,扣除#include 和 #define语句,共142个字节,但是速度较慢。

#define N 10 //计算N的阶乘,修改N的定义可计算200000以内任意数的阶乘
int a[N]={1},n=N,i,c,m;void main(){
for(;n>1;(a[i]=c)>0?m++:0,n--)
for(c=i=0;i<=m;i++)a[i]=(c+=a[i]*n)%10,c/=10;
for(;m>=0;)printf("%d",a[m--]);}


其实,我早在2000年末,就尝试过用较少的代码计算大数阶乘,请参阅帖子
有谁可以用四行代码求出1000000的阶乘!!!


另外,雨中飞燕也尝试过写类似的程序,请参阅雨中飞燕的博客
原创]四行代码算1000阶乘精确值 -- 雨中飞燕之家 -- 编程爱好者BLOG

...全文
1063 点赞 收藏 36
写回复
36 条回复
切换为时间正序
请发表友善的回复…
发表回复
rainday163 2009-04-26
Python那玩意儿的执行效率,能跟C相提并论么...
BS -ing
回复
popcoder 2009-04-24
[Quote=引用 32 楼 iambic 的回复:]
>python是支持大数运算的,而C语言不支持,不具可比性。
如果这就是写垃圾代码的理由,还是放弃C语言吧。
[/Quote]
Python那玩意儿的执行效率,能跟C相提并论么...
回复
iambic 2008-11-13
>python是支持大数运算的,而C语言不支持,不具可比性。
如果这就是写垃圾代码的理由,还是放弃C语言吧。
回复
Arthur_ 2008-11-13
沙发
回复
liangbch 2008-11-13
哈哈,好多人说这样没有意义。我以为,是否有意义,不能这么简单下结论。的确对于程序来说,算法或者程序的效率更有意义。但个人以为,计算机技术包括很多,除了算法,还有C语言,汇编语言,编译器,操作系统,数据库等,你不能说一种比另一种技术好。算法不是全部,如果如你所言,那个大家都研究算法好了。人类得以进步的一种主要原因,是人类永远不满足现状,就像体育界一样,追求更快,更高,好强,而对于计算机界,就是更小,更快了。
追求更短的源代码,更小的执行文件,就经济角度而言,毫无意义。就像许多吉尼斯世界纪录,他们本生没有多大意义一样,比如,能背诵4万为圆周率有什么意义呢?另一个例子,就如刘翔一样,跑得快本身有什么经济意义,需要他抓小偷吗,需要他当邮递员送信吗?如果需要更快的到达目的地,修铁路,造汽车,造飞机,甚至神舟飞船,都更有现实意义。

看不惯代码者,狠狠的说:垃圾。这个代码,原本就不是非要你看,也没有收你门票。这和工作中不一样,在工作中在维护代码时,看到写的不好的代码(如没有注释,没有缩进,3000行的函数,10000行的文件)也仍不住骂,垃圾!。彼代码和此代码不一样,彼代码是不得不看,必须要看懂的,看不懂老板不给你钱,看得慢了,会影响产品的进度。此代码是给竞赛者看的。而所有竞赛都具有同样的特点,难,轻易就完成了,会觉得没有成就感。越难越有挑战性,才约有吸引力,完成了才有成就感。

程序写久了,会尝试去挑战各种界限,如最快的速度,更高的效率,最小的源代码,最小的执行文件。这并不违背计算机精神,更小,更快,尽管有些技术本身没有经济意义。

鄙视代码者,不一定能写出这么短小的同样功能代码。就算你不是一个竞赛者,去分析一下这段代码,至少也可以学到一些东西,至少也可以见识一下不同的C语言语句的写法。我每每看到诡异的代码,难懂的代码(哪怕不合自己风格),只要觉得有可取之处,得会花时间去研究,屡有收获,诚所谓取长补短。从下面的这个程序,我就有不少的收获。 不错,难懂的代码是令人讨厌的,但许多是值得学习的。那个高度优化的FFT算法的一份源代码ooura-fft非常复杂,我至今也没有看懂,但是它的效率比我的快好多,我是不是该像你们一样,说声"垃圾"呢?

void main(int a)
{
char* x = "bB_Z#^B_Z#h1AI.BMB5#VB2]2:B]]=6#RB@1.]]L12#NB6N:]BN#JFHL1@D6#";
while(a = *x / 4) a -= 8, printf("\n%*s" + !!a, a, "_/_/_/" + *x++ % 4 * 2);
}

回复
qq675927952 2008-11-12
呵呵,up
回复
cyj626 2008-11-12
15楼怎么没有了????????????????????????????????????????????????
回复
cyj626 2008-11-12
[Quote=引用 13 楼 lunarfan 的回复:]
先占个坐,代码短不代表效率高。要比效率
[/Quote]
对头
回复
Han_Xiang 2008-11-12
用Java写高精度可以很短也很清晰吧,呵呵。

POJ上有两个人专门写短代码:

http://acm.pku.edu.cn/JudgeOnline/userstatus?user_id=funnything
http://acm.pku.edu.cn/JudgeOnline/userstatus?user_id=ozy4dm

其中,1025这个题ozy4dm只用了3233B,但我看他总共提交了两次,间隔没几分钟,第一次代码有7162B,估计可能是删除一些格式字符,第二次的代码都写到一行里了……

http://acm.pku.edu.cn/JudgeOnline/problem?id=1025

2300824 ozy4dm 1025 Accepted 80K 0MS GCC 7162B 2007-07-04 16:22:01
2300836 ozy4dm 1025 Accepted 72K 15MS GCC 3233B 2007-07-04 16:27:39
回复
lunarfan 2008-11-12
先占个坐,代码短不代表效率高。要比效率
回复
R9R9R9 2008-11-12
WOW....兄弟你好短哦.
回复
liangbch 2008-11-12
转我在另一个帖子的回复

我的一个帖子,招来无数板砖。看看我有必要解释解释了,可能有语言有不当处,先说一声抱歉,希望不要坏了大家的心情。

大多数回帖者教导我,代码要规范,要注意编程风格。事实上,我用C语言编程已经超过13年,和同事们比起来,我更在意代码的可读性,逻辑结构是否简单合理。我经常对自己写的代码和别人写的代码进行优化,使代码结构更简单,更清晰,更易于阅读。
我也读了一些关于编码规范,软件工程之类的书籍。其中包括下面的3本书籍,其中前2本是我自己购买的,第三本是公司购买的。

程序员修炼之道——从小工到专家
C++编码规范
代码大全

另外,我也阅读过许多开源项目的代码,包括GMP,apfloat等。对于”什么样的编程风格是好的“这个问题,我同时具有理论基础和实际经验。

我参加过信息产业部举办的白盒测试工程师的培训。熟知一些代码质量的度量标准。下面贴出函数的可维护性的一个质量度量因子。

PARA参数数
LVAR局部变量数
VOCF词汇频度
GOTO转移语句数
VG圈复杂度
STMT可执行语句数
AVGS平均语句长度
COMF注释频度
NBCALLING函数被调用次数
RETU返回语句数
DRCT_CALLS直接调用函数数 ……

也用过一些代码检测工具。我用过的代码检测工具有Logiscope, testbed, pclint.

很多人却我把精力花在算法方便,这比缩小代码更有意义,我认同这句话。实际上,我很喜欢算法,我的专家分绝大多数是在数据结构和算法得的,C++板块得分甚少。

在计算大数阶乘方面,我花了很多的时间去研究算法,也取得了非常好的效果,以效率计,在计算大数阶乘方面,极少有人能超过我或者达到我,目前知道的只有gxq和lcx。关于大数阶乘算法的研究过程,请看我早期发的帖子。

擂台赛:计算n!(阶乘)的精确值,速度最快者2000分

擂台赛:计算n!(阶乘)的精确值,速度最快者2000分送上(续) 专题开发/技术/项目

当然,算法玩腻了,也不妨尝试点别的,玩玩缩小目标代码(可执行文件)的大小,玩玩缩小源代码的大小,同样需要技巧,需要对编程语言充分的理解和掌握,那些鄙视我的回帖者,未必懂得这些技巧。

做一个目标文件最小的计算大数阶乘的程序,在早些年已经玩过了,请看。
擂台:用汇编语言计算大数阶乘,程序最小最快者1000分送上

该玩的都玩过了,所以这次玩一个尽力缩小源代码的计算大数阶乘的程序。为了实现某一功能,尽力写一个源代码最小的程序,国外早已有之,我不是第一个。我见过多个,那些奉劝多学习国外代码的朋友,没准儿我读过的代码比他们还多。


另外,说一句题外话,我记得袁峰大侠说过,高手是自封的。意思大概是这样的,要想成为高手,首先把自己当作一个高手,自己的一言一行都想高手看齐,言必行,行必果,要对自己负责,要对自己说过的话复杂,要树立自己的威信,不要说一些不负责任的话。
回复
lbjfeng 2008-11-12
看不懂,看不明白
不过,还是顶一下~~~
不知道,是不是对于阶乘,还有更好的算法~~
关注
回复
genuc 2008-11-12
mark
回复
yzfyzyl 2008-11-12
呵呵。。


o(∩_∩)o

飞燕算法群:46520219
回复
zhangqqqf 2008-11-12
我X,我都F了. 我也不知道LZ想拿着这破代码炫耀到什么时候呢?

你是不是以为时间复杂度以及空间复杂度一般菜鸟直观上看不出来难以表达对你敬仰之情所以整了个看代码是否短小来让菜鸟尊称你为大侠你才满意?

你那你把破烂代码翻译成汇编看看节省啥了?

写纸上省纸?
回复
frisky_lobo 2008-11-12
代码短小精悍不是以字节为单位的,而是以语句指令为单位统计的
回复
hjzwl1018 2008-11-12
狠了。
回复
liangbch 2008-11-12
to 22楼,对使用SSE2指令求大数乘法,我们曾经探讨过,在 千分求汇编优化:UInt96x96To192(...) 这个帖子中,我便是3个主要解答人之一,其中之一是帖主,另一个是
DelphiGuy。
回复
liangbch 2008-11-12
to 22楼,对使用SSE2指令求大数乘法,我们曾经探讨过,在 千分求汇编优化:UInt96x96To192(...) 这个帖子中,我便是3个主要解答人之一,其中之一是帖主,另一个是
DelphiGuy。
回复
发动态
发帖子
C语言
创建于2007-09-28

6.2w+

社区成员

C语言相关问题讨论
申请成为版主
社区公告
暂无公告