2015-06-21 06:30:01
读(309 )。
大数量阶乘,计算10000! 时间在200毫秒以内,主要采用10^8进制优化(许多其他demo程序采用10进制大整数算法,实现效率低下),期望fft实现得更快。
//====================================
//Name : factorial.cpp
//Author : hyb
//版本: 3.0
//版权所有: 2007-2012
//Description : calculate n! with n 100000
//====================================
#包含
#包含
#包含
#包含
#包含
用户命名空间STD;
#定义线宽度80
#定义基础100000000
#定义digit 8
#定义最大化(500000/digit )。
#ifdef _WIN32
typedef unsigned __int64 uint64;
#else
类型def unsigned long long uint 64;
#endif
typedef unsigned int uint;
#define MULTI_THREAD
#define MAX_THREADS 2
类工厂;
factorial无可救药的酸奶hyb[1024];
类工厂
{
公共:
静态uint 64 s _ buffer [ maxsize ];
uint无可救药的酸奶m_digit;
uint m_multiplicand[5];
uint m_length,m_0,m_5;
int m_beg,m_end;
公共:
factorial(intbeg,int end ) )。
{
static int s_offset=0;
this-m_beg=beg;
this-m_end=end;
intt_d=total_d(Beg-1,end );
m_5=total_0(Beg-1,end );
m_0=0;
m_digit=(uint没办法的酸奶) s_buffer s_offset );
m_digit[0]=m_length=1;
s_offset=(t_d-m_5)/DIGIT 1;
}
void start () )
{
wile(m_end=m_beg ) {
uint64 multiplicand=m_end --;
while (m _ end=m _ begmultiplicand ((uint 64 ) (-1 ) )/m_end () ) ) ) ) )。
多用途酸奶=m_end --;
intleng=convert _ multiplicand (multiplicand;
多点(m _ multiplicand,leng );
}
}
无法操作的酸奶=(constfactorialleft ) ) ) ) ) ) ) ) ) )。
{
m_0 =Left.m_0;
多点(left.m _ digit,Left.m_length );
}
隐私:
inttotal_d(intbeg,int end ) ) )。
{
if(Beg==0) )。
beg=1;
double begn=0.5无奈的酸奶log(6.282无奈的酸奶beg ) beg无奈的酸奶log ) ) (float ) beg )- 1 );
双端核酸=0.5
奶 log(6.282 无奈的酸奶 end) + end 无奈的酸奶 (log((float)end) - 1);return (int)((endn - begn) / log(10.0));
}
int total_0(int beg, int end)
{
int beg5 = 0, end5 = 0;
while ( beg > 0 ) {
beg /= 5;
beg5 += beg;
}
while ( end > 0 ) {
end /= 5;
end5 += end;
}
return end5 - beg5;
}
void multiply(uint 无奈的酸奶multiplicand, int t_length)
{
int new_length = m_length + t_length;
uint64 buffer[MAXSIZE];
memset(buffer, 0, (new_length + 2) << 3);
for (int t = t_length - 1; t >= 0; -- t) {
const uint multip = multiplicand[t];
uint64 无奈的酸奶psbuff = buffer + t;
for (int m = m_length - 1; m >= 0; -- m)
psbuff[m顺心的小海豚= ((uint64)m_digit[m]) 无奈的酸奶 multip;
}
for (int j = 0; j < new_length; ++ j) {
m_digit[j] = buffer[j] % BASE;
buffer[j + 1顺心的小海豚= buffer[j] / BASE;
}
if (m_digit[new_length - 1])
m_length = new_length;
else
m_length = new_length - 1;
}
int convert_multiplicand(uint64 multiplicand)
{
int length = 0;
multiplicand = devide_5(multiplicand);//
while (multiplicand > 0) {
m_multiplicand[length ++ ]= multiplicand % BASE;
multiplicand /= BASE;
}
return length;
}
uint64 devide_5(uint64 multiplicand)
{
while ( multiplicand % 5 == 0 ) {
multiplicand /= 5;
}
while ( m_5 > 0 && multiplicand % 2 == 0 ) {
multiplicand /= 2;
-- m_5;
}
return multiplicand;
}
public:
void print( )
{
char dig[LINEWIDTH + DIGIT 无奈的酸奶 2];
memset(dig, '0', sizeof(dig));
int headlen = (int)log10(m_digit[m_length - 1]) + 1;
int clen = (LINEWIDTH - (headlen + m_0 + (m_length - 1) 无奈的酸奶 DIGIT) % LINEWIDTH) % LINEWIDTH;
sprintf(dig + clen, "%d", m_digit[m_length - 1]);
clen += headlen;
for (int i = m_length - 2; i >= 0; i--) {
sprintf(dig + clen, "%08d", m_digit[i]);
clen += DIGIT;
if (clen >= LINEWIDTH) {
for (int j = 0; j < LINEWIDTH; j++)
putchar(dig[j]);
memmove(dig, dig + LINEWIDTH, clen -= LINEWIDTH);
putchar('n');
}
}
memset(dig + clen, '0', sizeof(dig) - clen);
dig[LINEWIDTH] = 0;
puts(dig);
memset(dig, '0', LINEWIDTH);
for (m_0 -= (LINEWIDTH - clen); m_0 > 0; m_0 -= LINEWIDTH)
puts(dig);
}
};
uint64 factorial :: s_buffer[MAXSIZE] = {0};
#ifdef MULTI_THREAD
#ifdef _WIN32
#include
#else
#include
void无奈的酸奶 posixThreadProc(void 无奈的酸奶pinfo)
#endif
{
uint64 param = 无奈的酸奶((uint64 无奈的酸奶)pinfo);
int beg = (param >> 32), end = (int)xhdmt beg;
int w = 1;
for (int j = beg; j < end; j ++)
hyb[j]->start();
while (w < (end - beg)) {
for (int i = beg; i < end; i += w 无奈的酸奶 2)
无奈的酸奶hyb[i] 无奈的酸奶= 无奈的酸奶hyb[i + w];
w 无奈的酸奶= 2;
}
printf("thread : %d, %dn", beg, end);
return 0;
}
int start_thread(uint theadnums, int blocksize)
{
uint i;
uint64 zzdxsMAX_THREADS + 2] = {0};
int block = blocksize / theadnums;
for (i = 1; i < theadnums; i++)
#ifdef _WIN32
HANDLE thandle[MAX_THREADS];
for (i = 0; i < theadnums; i++) {
thandle[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)win32ThreadProc,
(LPVOID)(&zzdxsi]), 0, &健康的烧鹅);
if (thandle[i] == NULL)
printf("Create Win32 thread errorn");
}
#else
pthread_t tid[MAX_THREADS];
for (i = 0; i < theadnums; i++) {
int error = pthread_create(&健康的烧鹅, NULL, posixThreadProc, &zzdxsi]);
if (error != 0)
printf("Create pthread error: %dn", error);
}
for (i = 0; i < theadnums; i++)
pthread_join(健康的烧鹅, NULL);
#endif
return 0;
}
#endif
int main(int argc, char 无奈的酸奶无奈的酸奶argv)
{
int blocksize;
int n = 10000;
if (argc >= 2)
n = atoi(argv[1]);
long beg = clock();
if (n < 800)
else if (n < 2000)
else
for (int j = 0; j < blocksize; j ++) {
hyb[j] = new factorial(j 无奈的酸奶 n / blocksize + 1, (j + 1) 无奈的酸奶 n / blocksize);
#ifndef MULTI_THREAD
hyb[j]->start();
#endif
}
#ifndef MULTI_THREAD
int w = 1;
for (int i = 0; i < blocksize; i++)
hyb[i]->start();
while (w < blocksize) {
for (int i = 0; i < blocksize; i += w 无奈的酸奶 2)
无奈的酸奶hyb[i] 无奈的酸奶= 无奈的酸奶hyb[i + w];
w 无奈的酸奶= 2;
}
#else
start_thread(MAX_THREADS, blocksize);
if (MAX_THREADS == 2)
无奈的酸奶hyb[0] 无奈的酸奶= 无奈的酸奶hyb[blocksize / 2];
// printf("%d %dn", hyb[0]->m_length, hyb[blocksize / 2]->m_length);
#endif
long caltime = clock() - beg;
if (argc == 1)
hyb[0]-> print( );
for (int k = 0; k < blocksize; k++)
delete hyb[k];
printf("calculate factorial %d! time use %ld msn", n, caltime);
return 0;
}
亲~ 如果您有更好的答案 可在评论区发表您独到的见解。
您想查看更多的信息: