| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1215 人关注过本帖, 2 人收藏
标题:求指点(大数字的运算问题)
只看楼主 加入收藏
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
收藏
得分:0 
以下是引用小鱼儿c在2012-3-9 13:47:37的发言:

我就是想知道有什么高效的。
对大数运算 具体什么有办法可以实现。
n必须100位以前。
效率还是要求蛮高的

n必须100位以前。

那直接算比较快吧 每位存一个数的话 100位的平方也不过算10000次乘法 连续执行的话一个乘法大约也就是3个时钟周期 3万个时钟周期 2GHz的CPU 你算算多少秒罢

可以先写一个不考虑小数的直接乘法看看 那很简单 嵌套循环
2012-03-09 14:40
czz5242199
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:小飞侠
威 望:4
帖 子:660
专家分:2400
注 册:2011-10-26
收藏
得分:0 
回复 10楼 小鱼儿c
现在写代码在代码层次的优化效果其实是很不明显的,就比如大数运算写来写去几种方式几种数据结构最后的运算速度差距绝对是微乎其微的
2012-03-09 14:51
laoyang103
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:内蒙古包头
等 级:贵宾
威 望:19
帖 子:3082
专家分:11056
注 册:2010-5-22
收藏
得分:20 
回复 10楼 小鱼儿c
加减法没啥优化的  可以优化的乘除模法  以前说过要给你大数模板  但是忘了  实在不好意思

先奉上两道题  北航的超级最小公倍数  大书乘除模
http://www.
超级最小公倍数
时间限制:8000 ms  |  内存限制:16384 KB
描述
给2个正整数a,b(1<=a,b<=10100),求a和b的最小公倍数。

输入
输入包含多组数据,每组数据一行,包含两个正整数a和b,中间以一个空格隔开。输入以0 0结束。

输出
每组数据输出一行,为a,b的最小公倍数。

样例输入
123 321
123456789 987654321
0 0
样例输出
13161
13548070123626141

杭电的一万的阶乘  典型大数乘小数优化

N!
Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 28903    Accepted Submission(s): 7929


Problem Description
Given an integer N(0 ≤ N ≤ 10000), your task is to calculate N!

 

Input
One N in one line, process to the end of file.

 

Output
For each N, output N! in one line.

 

Sample Input
1
2
3
 

Sample Output
1
2
6
 
上面两个题如果效率不够高  绝对保证超时

[ 本帖最后由 laoyang103 于 2012-3-9 14:58 编辑 ]

                                         
===========深入<----------------->浅出============
2012-03-09 14:55
laoyang103
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:内蒙古包头
等 级:贵宾
威 望:19
帖 子:3082
专家分:11056
注 册:2010-5-22
收藏
得分:0 
一万阶乘  218MS出结果
程序代码:
#include<stdio.h>
void Fact(int n)
{
    int a[20000] = {1},f,i,j,len = 1;
    for(i = 2;i<=n;i++)
    {
        for(f = 0,j = 0;j<len;j++)
        {
            if(!(a[j] || f))continue;
            a[j] = a[j]*i + f;
            f = a[j]/10000;
            a[j] %= 10000;
        }
        if(f)a[len++] = f;
    }
    printf("%d",a[--len]);
    while(len--)printf("%04d",a[len]);
    printf("\n");
}
int main(void)
{
    int n;
    while(~scanf("%d", &n))
        Fact(n);
    return 0;
}
超级最小公倍数  借助杨大哥优化的除法算法
程序代码:
#include<stdio.h>
#include<string.h>
void output(char * a, int an)
{
    int i;
    for(i = an - 1; i >= 0; i--) putchar(a[i] + '0');
    putchar('\n');
}
void format(char * a, int an)
{
    int i, j;
    char t;
    for(i = 0, j = an - 1; i < j; i++, j--)
    {
        a[i] -= '0';
        a[j] -= '0';
        t = a[i];
        a[i] = a[j];
        a[j] = t;
    }
    if(i == j) a[i] -= '0';
}
void mul(char * a, int * an, char * b, int bn)
{
    char t[256], s[256] = {0};
    int i, j, k, f;
    for(i = 0; i < bn; i++)
    {
        if(b[i] == 0) continue;
        for(j = 0; j < i; t[j++] = 0);
        for(f = 0, k = 0; k < *an; k++)
        {
            t[j] = b[i] * a[k] + f;
            f = t[j] / 10;
            t[j++] %= 10;
        }
        if(f) t[j++] = f;
        for(f = 0, k = 0; k < j; k++)
        {
            s[k] += t[k] + f;
            if(s[k] >= 10){ s[k] -= 10; f = 1;} else f = 0;
        }
        if(f)s[j++] = 1;
    }
    for(i = 0; i < j; a[i] = s[i++]);
    *an = j;
}
void div(char * a, int * an, char * b, int bn)
{
    char t[256], r[256] = {0};
    int f, i, j;
    if(*an < bn)
    {
        a[0] = 0;
        a[1] = 0;
        *an = 1;
        return;
    }
    for(i = *an - bn; i >= 0; i--)
    {
        for(f = 0, j = 0; j < bn; j++)
        {
            t[j] = a[i + j] - b[j] - f;
            if(t[j] < 0){ t[j] += 10; f = 1;} else f = 0;
        }
        if(a[bn + i] - f >= 0)
        {
            a[bn + i] -= f;
            for(j = 0; j < bn; a[i + j] = t[j++]);
            r[i]++;
            i++;
        }
    }
    for(i = *an - bn; i && !r[i]; i--);
    for(j = i; j >= 0; a[j] = r[j--]);
    *an = i + 1;
    a[*an] = 0;
}

void mod(char * a, int * an, char * b, int bn)
{
    if(*an<bn)
        return ;
    char c[101] = {0};
    int i,j,k,low;
    for(i = *an-bn;i>=0;--i)
    {
        low = 0;
        for(j = 0;j<bn;++j)
        {
            c[j] = a[i+j] - b[j] - low;
            if(c[j]<0)
            {c[j] += 10;low = 1;}
            else
                low = 0;
        }
        if(a[i+bn] - low >= 0)
        {
            a[i+bn] -= low;
            for(k = 0;k<bn;++k)
                a[i+k] = c[k];
            i++;
        }
    }
    for(i = bn-1;!a[i]&&i>=0;i--);
    *an = i+1;
}

void lcm(char *a, int * an, char *b, int bn)
{
    char ta[256], tb[256], *pa, *pb, *pt;
    int pan, pbn, ptn, i;
    for(i = 0; i <= *an; ta[i] = a[i++]);
    for(i = 0; i <= bn; tb[i] = b[i++]);
    pa = ta;
    pb = tb;
    pan = *an;
    pbn = bn;
    mod(pa, &pan, pb, pbn);
    while(pan > 1 || pa[0])
    {
        pt = pa;
        pa = pb;
        pb = pt;
        ptn = pan;
        pan = pbn;
        pbn = ptn;
        mod(pa, &pan, pb, pbn);
    }
    div(a, an, pb, pbn);
    mul(a, an, b, bn);
}
int main()
{
    char a[256], b[256];
    int an, bn;
    while(scanf("%s %s", a, b), a[0] > '0')
    {
        an = strlen(a);
        bn = strlen(b);
        format(a, an);
        format(b, bn);
        //mod(a, &an, b, bn);
        lcm(a, &an, b, bn);
        output(a, an);
    }
    return 0;
}





                                         
===========深入<----------------->浅出============
2012-03-09 14:57
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
收藏
得分:10 
对于直接乘 每个单元可以放4位10进制数 也就是10000进制 因为9999*9999=99980001=0x5F592E1 不溢出

于是 100位25个int 625次乘法就可以了

以上讨论的是32位环境 64位更好


2012-03-09 14:57
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
收藏
得分:0 
以下是引用czz5242199在2012-3-9 14:51:32的发言:

现在写代码在代码层次的优化效果其实是很不明显的,就比如大数运算写来写去几种方式几种数据结构最后的运算速度差距绝对是微乎其微的

对 用算法在时间复杂度上提升效率才是王道

不过即使都是快速傅里叶 不同实现的效率也不同 具体可以参考fftw网站上的测评 我网太慢就不贴网站了、、、
2012-03-09 14:59
Devil_W
Rank: 10Rank: 10Rank: 10
等 级:青峰侠
威 望:9
帖 子:1160
专家分:1797
注 册:2009-9-14
收藏
得分:0 
以下是引用laoyang103在2012-3-9 14:55:04的发言:

加减法没啥优化的  可以优化的乘除模法  以前说过要给你大数模板  但是忘了  实在不好意思

先奉上两道题  北航的超级最小公倍数  大书乘除模
http://www.
超级最小公倍数
时间限制:8000 ms  |  内存限制:16384 KB
描述
给2个正整数a,b(1<=a,b<=10100),求a和b的最小公倍数。

输入
输入包含多组数据,每组数据一行,包含两个正整数a和b,中间以一个空格隔开。输入以0 0结束。

输出
每组数据输出一行,为a,b的最小公倍数。

样例输入
123 321
123456789 987654321
0 0
样例输出
13161
13548070123626141

杭电的一万的阶乘  典型大数乘小数优化

N!
Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 28903    Accepted Submission(s): 7929


Problem Description
Given an integer N(0 ≤ N ≤ 10000), your task is to calculate N!

 

Input
One N in one line, process to the end of file.

 

Output
For each N, output N! in one line.

 

Sample Input
1
2
3
 

Sample Output
1
2
6
 
上面两个题如果效率不够高  绝对保证超时



Devil_Wang    正确    619ms    88KB    g++    03-09 14:43
2012-03-09 15:00
laoyang103
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:内蒙古包头
等 级:贵宾
威 望:19
帖 子:3082
专家分:11056
注 册:2010-5-22
收藏
得分:0 
回复 17楼 Devil_W
上面的代码5MS

                                         
===========深入<----------------->浅出============
2012-03-09 15:36
Devil_W
Rank: 10Rank: 10Rank: 10
等 级:青峰侠
威 望:9
帖 子:1160
专家分:1797
注 册:2009-9-14
收藏
得分:0 
以下是引用laoyang103在2012-3-9 15:36:29的发言:

上面的代码5MS


so what,我的那code可以作为一个common module。
你那个可以吗?
2012-03-09 15:59
laoyang103
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:内蒙古包头
等 级:贵宾
威 望:19
帖 子:3082
专家分:11056
注 册:2010-5-22
收藏
得分:0 
回复 19楼 Devil_W
呵呵  我还是穷学生  菜鸟一个 我哪里知道什么叫公用模式


                                         
===========深入<----------------->浅出============
2012-03-09 16:03
快速回复:求指点(大数字的运算问题)
数据加载中...
 
   



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

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