| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 4873 人关注过本帖, 2 人收藏
标题:[公告]挑战C板块的 阶乘算法
只看楼主 加入收藏
取消关键字高亮
kai
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:52
帖 子:3450
专家分:59
注 册:2004-4-25
收藏
得分:0 
knocker,
你的程序在哪里啊?

自由,民主,平等,博爱,进步.
中华民国,我的祖国,中华民国万岁!中华民国加油!
本人自愿加入中国国民党,为人的自由性,独立性和平等性而奋斗!
2005-11-01 20:01
Knocker
Rank: 8Rank: 8
等 级:贵宾
威 望:47
帖 子:10454
专家分:603
注 册:2004-6-1
收藏
得分:0 
你的在什么地方?

九洲方除百尺冰,映秀又遭蛮牛耕。汽笛嘶鸣国旗半,哀伤尽处是重生。     -老K
治国就是治吏。礼义廉耻,国之四维。四维不张,国之不国。   -毛泽东
2005-11-01 20:10
kai
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:52
帖 子:3450
专家分:59
注 册:2004-4-25
收藏
得分:0 
my code:
[CODE]

#include <iostream>
#include <cstdlib>
#include <climits>
#include <cmath>
#include <iomanip>
#include <cfloat>
#include <windows.h>
using namespace std;

class Factorial
{
private:
int n;
int length;
int base;
int * result;
void setLength()
{
int max = INT_MAX / n;
for( ; max>=base; base = base*10)
;
base = base / 10;
double test = 0;
for(int i = 2; i<= n; i++)
test += log10(i);
length = (int) (test) / (log10(base)) + 1;
}
void mul()
{
int carry = 0;
int r = 0;
for(int j = 3; j<=n; j++)
{
for(int i = length - 1; i>=0; i--)
{
r = result[i] * j + carry;
result[i] = r%base;
carry = r/base;
}
}
}
public:
Factorial(int n)
{
this->n = n;
base = 10;
setLength();
result = new int[length];
memset(result, 0, length*sizeof(int));
result[length-1] = 2;
}
~Factorial()
{
if(result)
delete [] result;
}
void fact()
{
memset(result, 0, length*sizeof(int));
result[length-1] = 2;
mul();
}
void display()
{
cout<<result[0];
cout.fill('0');
for(int i = 1; i<length; i++)
{
cout<<setw(log10(base))<<result[i];
}
cout<<endl;
}
};

int main()
{
LARGE_INTEGER listart,lifinish,lifrequency;
__int64 result;
int n = 10000;
QueryPerformanceCounter( &listart );
// excution
Factorial fac(n);
fac.fact();
QueryPerformanceCounter(&lifinish);
QueryPerformanceFrequency(&lifrequency);
result = (lifinish.QuadPart - listart.QuadPart)*1000000/lifrequency.QuadPart;
char dauer[20];
_i64toa(result, dauer, 10);
fac.display();
cout<<dauer<<endl;

system("pause");
return 0;
}


[/CODE]

自由,民主,平等,博爱,进步.
中华民国,我的祖国,中华民国万岁!中华民国加油!
本人自愿加入中国国民党,为人的自由性,独立性和平等性而奋斗!
2005-11-01 20:11
kai
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:52
帖 子:3450
专家分:59
注 册:2004-4-25
收藏
得分:0 

走了,明天再来看你的。


自由,民主,平等,博爱,进步.
中华民国,我的祖国,中华民国万岁!中华民国加油!
本人自愿加入中国国民党,为人的自由性,独立性和平等性而奋斗!
2005-11-01 20:13
Knocker
Rank: 8Rank: 8
等 级:贵宾
威 望:47
帖 子:10454
专家分:603
注 册:2004-6-1
收藏
得分:0 

[QUOTE]#include <stdio.h>
#include <math.h>
#include <malloc.h>
#include <time.h>
#include <stdlib.h>
#define CARRY 100000
clock_t start,end ;
int GetFactorialMemSize(int n);
long*InitiFactorialMem(int Size);
int Factorial(register long*FactorialMem,int n);
void PrintFactorial(long*FactorialMem,int Start);
int main(void)
{
int N,FactorialStart,FactorialMemSize ;
long*PFactorial ;
char Key='y' ;
while(Key=='y'||Key=='Y')
{
printf("N=?");
while(scanf("%d",&N)!=1)getchar();
FactorialMemSize=GetFactorialMemSize(N)/5+1 ;
PFactorial=InitiFactorialMem(FactorialMemSize);
start=clock();
FactorialStart=Factorial(PFactorial,N);
end=clock();
printf("\n计算%d!花费: %f 秒\n按回车打印....\n\n",N,(float)(end-start)/CLK_TCK);
getchar();
getchar();
start=clock();
PrintFactorial(PFactorial,FactorialStart);
end=clock();
printf("\n\n输出%d!花费: %f 秒\n",N,(float)(end-start)/CLK_TCK);
free(PFactorial);
printf("继续? y 或 Y 退出? 任意键\n");
Key=getchar();
}
return 0 ;
}
/*-----------------------------------------------------------------*/
int GetFactorialMemSize(int n)
{
double sum=1.0 ;
int i ;
for(i=1;i<=n;i++)
sum+=log10((long double)i);
return(int)sum ;
}
/*-------------------------------------------------------------------*/
long*InitiFactorialMem(int Size)
{
long*FactorialMem=(long*)calloc(Size,sizeof(long));
if(!FactorialMem)
{
printf(" Allocation Error !\n");
exit(1);
}
return FactorialMem ;
}
/*------------------------------------------------------------------*/
int Factorial(register long*FactorialMem,int n)
{
int NotZero=0,End=0,i,j ;
long int CARRY_number ;
register long int tem ;
FactorialMem[0]=1 ;
for(i=1;i<=n;i++)
{
CARRY_number=0 ;
for(j=NotZero;j<=End;j++)
{
tem=FactorialMem[j]*i+CARRY_number ;
CARRY_number=tem/CARRY ;
FactorialMem[j]=tem%CARRY ;
}
while(!FactorialMem[NotZero])NotZero++;
if(CARRY_number)FactorialMem[++End]=CARRY_number ;
}
return End ;
}
/*-------------------------------------------------------------------*/
void PrintFactorial(long*FactorialMem,int Start)
{
printf("%ld",FactorialMem[Start--]);
while(Start>=0)printf("%.5ld",FactorialMem[Start--]);
}[/QUOTE]


九洲方除百尺冰,映秀又遭蛮牛耕。汽笛嘶鸣国旗半,哀伤尽处是重生。     -老K
治国就是治吏。礼义廉耻,国之四维。四维不张,国之不国。   -毛泽东
2005-11-01 20:14
Knocker
Rank: 8Rank: 8
等 级:贵宾
威 望:47
帖 子:10454
专家分:603
注 册:2004-6-1
收藏
得分:0 

你传个执行文件上来,你的程序我编译不了,

KKK.cpp
Linking...
LIBC.lib(wincrt0.obj) : error LNK2001: unresolved external symbol _WinMain@16
Release/KKK.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.

KKK.exe - 2 error(s), 0 warning(s)


九洲方除百尺冰,映秀又遭蛮牛耕。汽笛嘶鸣国旗半,哀伤尽处是重生。     -老K
治国就是治吏。礼义廉耻,国之四维。四维不张,国之不国。   -毛泽东
2005-11-01 20:24
Knocker
Rank: 8Rank: 8
等 级:贵宾
威 望:47
帖 子:10454
专家分:603
注 册:2004-6-1
收藏
得分:0 
你的程序是我一倍,慢一倍

九洲方除百尺冰,映秀又遭蛮牛耕。汽笛嘶鸣国旗半,哀伤尽处是重生。     -老K
治国就是治吏。礼义廉耻,国之四维。四维不张,国之不国。   -毛泽东
2005-11-01 20:32
Knocker
Rank: 8Rank: 8
等 级:贵宾
威 望:47
帖 子:10454
专家分:603
注 册:2004-6-1
收藏
得分:0 
3000分是我的了

九洲方除百尺冰,映秀又遭蛮牛耕。汽笛嘶鸣国旗半,哀伤尽处是重生。     -老K
治国就是治吏。礼义廉耻,国之四维。四维不张,国之不国。   -毛泽东
2005-11-01 20:34
Knocker
Rank: 8Rank: 8
等 级:贵宾
威 望:47
帖 子:10454
专家分:603
注 册:2004-6-1
收藏
得分:0 

环境:PII 233 winme
我的


[QUOTE]N=?10000
计算10000!花费: 4.500000 秒
按回车打印....

............(略去)
0000000000000000000000000000000000
0000000000000000000000000000000000
0000000000000000000000000000000000
输出10000!花费: 6.590000 秒
继续? y 或 Y 退出? 任意键[/QUOTE]

你的,计算部分就要

23秒多


九洲方除百尺冰,映秀又遭蛮牛耕。汽笛嘶鸣国旗半,哀伤尽处是重生。     -老K
治国就是治吏。礼义廉耻,国之四维。四维不张,国之不国。   -毛泽东
2005-11-01 20:40
zinking
Rank: 7Rank: 7Rank: 7
等 级:贵宾
威 望:35
帖 子:916
专家分:0
注 册:2004-12-5
收藏
得分:0 
高兴什么,你的也不是最快的,我查到一种算法实现了,0.07秒,我这里只有思路。
所以,knocker你的程序也不是最强的!所以不要太k........
阶乘,是求一组数列的乘积,其效率的高低,一、是取决于高精度乘法算法,二、是针对阶乘自身特点算法的优化。
前者,是一种广为习知的技术,虽然不同算法效率可天壤之别,但终究可以通过学习获得,甚至可用鲁迅先生的“拿来主义”;
后者,则有许多的发展空间,这里我将介绍一种由我完全独创的一种方法,欢迎大家讨论,如能起到“抛砖引玉”的效果,那就真正达到了目的。

我在开发“阶乘”类算法时,始终遵循如下原则:
  • 参与高精度乘法算法的两数,大小应尽可能地相近;
  • 尽可能将乘法转化为乘方;
  • 尽可能地优先调用平方;

言归正转,下面以精确计算 1000! 为例,阐述该算法:

记 F1(n) = n*(n-1)*...*1;
F2(n) = n*(n-2)*...*(2 or 1);
Pow2(r) = 2^r;
有 F1(2k+1) = F2(2k+1) * F2(2k)
= Pow2(k) * F2(2k+1) * F1(k),
F1(2k) = Pow2(k) * F2(2k-1) * F1(k),
及 Pow2(u) * Pow2(v) = Pow2(u+v),

∴ 1000! = F1(1000)
= Pow2(500)*F2(999)*F1(500)
= Pow2(750)*F2(999)*F2(499)*F1(250)
= Pow2(875)*F2(999)*F2(499)*F2(249)*F1(125)
= Pow2(937)*F2(999)*F2(499)*F2(249)*F2(125)*F1(62)
= Pow2(968)*F2(999)*F2(499)*F2(249)*F2(125)*F2(61)*F1(31)
= Pow2(983)*F2(999)*F2(499)*F2(249)*F2(125)*F2(61)*F2(31)*F1(15)
= ...

如果你预存了某些小整数阶乘(比如这里的“F1(15)”),则可提前终止分解,否则直至右边最后一项为“F1(1)”为止;这样,我们将阶乘转化为2的整数次幂与一些连续奇数的积(或再乘以一个小整数的阶乘);

http://kongfuziandlife. http://codeanddesign.
2005-11-01 22:01
快速回复:[公告]挑战C板块的 阶乘算法
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.041831 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved