| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 5115 人关注过本帖
标题:c语言第一次接触高精度乘法,求代码。
只看楼主 加入收藏
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:528
帖 子:9007
专家分:53942
注 册:2011-1-18
收藏
得分:0 
程序代码:
#include <stdio.h>
#include <string.h>

char* foo( const char* a, const char* b, char c[static 200001] )
{
    memset( c, 0, 200001 );

    const size_t alen = strlen(a);
    const size_t blen = strlen(b);
    for( size_t ai=0; ai!=alen; ++ai )
    {
        unsigned carry = 0;
        for( size_t bi=0; bi!=blen; ++bi )
        {
            carry += c[200000-ai-bi-1] + (a[alen-ai-1]-'0')*(b[blen-bi-1]-'0');
            c[200000-ai-bi-1] = carry % 10;
            carry /= 10;
        }
        if( carry != 0 )
            c[200000-ai-blen-1] = carry;
    }

    char* p = &c[200000-1];
    for( size_t i=0; i!=200000; ++i )
    {
        c[i] += '0';
        if( p==&c[200000-1] && c[i]!='0' )
            p = c+i;
    }
    return p;
}

int main( void )
{
    //{ // test
    //    char c[200001];
    //    printf( "%s\n", foo("0","0",c) );
    //    printf( "%s\n", foo("0","123",c) );
    //    printf( "%s\n", foo("123","0",c) );
    //    printf( "%s\n", foo("999","99",c) ); // 98901
    //    printf( "%s\n", foo("999","999",c) ); // 998001
    //    printf( "%s\n", foo("86420","9753111111",c) ); // 842863862212620
    //}

    char a[100001], b[100001], c[200001];
    scanf( "%s%s", a, b );
    printf( "%s\n", foo(a,b,c) );

    return 0;
}
2016-10-25 10:43
RockCarry
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:13
帖 子:662
专家分:58
注 册:2005-8-5
收藏
得分:3 
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define MAX_LNUM_SIZE  32
#define DUMP_LNUM      1

#if DUMP_LNUM
static void dump_lnum_buf(const char *comment, char *lnum)
{
    int i;
    printf("%s: ", comment);
    for (i=0; i<MAX_LNUM_SIZE; i++) {
        printf("%2d ", lnum[i]);
    }
    printf("\n");
}
#endif

// handle carry of large number
static void lnum_carry(char *a)
{
    int i, c = 0;

#if DUMP_LNUM
    dump_lnum_buf("+lnum_carry", a);
#endif
   
    for (i=MAX_LNUM_SIZE-1; i>=0; i--) {
        a[i] += c;
        c     = a[i] / 10;
        a[i] %= 10;
    }

#if DUMP_LNUM
    dump_lnum_buf("-lnum_carry", a);
#endif
}

// a = a + (b <<< b_shift)
static void lnum_add(char *a, char *b, int b_shift)
{
    int i, j;

#if DUMP_LNUM
    dump_lnum_buf("+lnum_add a", a);
    dump_lnum_buf("+lnum_add b", b);
#endif

    for (i=0,j=b_shift; j<MAX_LNUM_SIZE; i++,j++) {
        a[i] += b[j];
    }

    lnum_carry(a);

#if DUMP_LNUM
    dump_lnum_buf("-lnum_add a", a);
#endif
}

static void lnum_to_string(char *str, char *lnum)
{
    int i = 0;
    int j = 0;

    for (; i<MAX_LNUM_SIZE; i++) {
        if (lnum[i]) break;
    }

    for (; i<MAX_LNUM_SIZE; i++) {
        str[j++] = lnum[i] + '0';
    }

    str[j] = '\0';
}

void lnum_multiply(char *result, char *a, char *b)
{
    char *lr = NULL;
    char *lt = NULL;
    int   nda= strlen(a);
    int   ndb= strlen(b);
    int   i, j;

    lr = calloc(1, MAX_LNUM_SIZE);
    lt = calloc(1, MAX_LNUM_SIZE);
    if (!lr || !lt) {
        printf("failed to allocate memory !\n");
        goto exit;
    }

    if (nda < ndb) { // swap ta & tb
        char *p;
        int   t;
        p = a; t   = nda;
        a = b; nda = ndb;
        b = p; ndb = t;
    }

    for (i=0; i<ndb; i++) {
        for (j=0; j<nda; j++) {
            lt[MAX_LNUM_SIZE - j - 1] = (a[nda-j-1] - '0') * (b[ndb-i-1] - '0');
        }
        lnum_add(lr, lt, i);
    }

    lnum_to_string(result, lr);

exit:
    if (lr) free(lr);
    if (lt) free(lt);
}

#if 1
int main(int argc, char *argv[])
{
    char result[MAX_LNUM_SIZE] = {0};
    if (argc < 3) {
        printf("large number multiply program v1.0\n");
        printf("written by rockcarry@\n");
        printf("usage: multiply 123 456\n");
        return 0;
    }
    lnum_multiply(result, argv[1], argv[2]);
    printf("%s * %s = %s\n", argv[1], argv[2], result);
}
#endif





[此贴子已经被作者于2016-10-25 11:51编辑过]

2016-10-25 11:20
RockCarry
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:13
帖 子:662
专家分:58
注 册:2005-8-5
收藏
得分:0 
我也来贡献一个代码,已经简单编译运行测试过了
这种算法速度还是不够快的,快速算法,是需要用到 FFT 的
2016-10-25 11:22
RockCarry
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:13
帖 子:662
专家分:58
注 册:2005-8-5
收藏
得分:0 
精简代码版本:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define MAX_LNUM_SIZE  256

// handle carry of large number
static void lnum_carry(char *a, int start, int end)
{
    int i, c = 0;
    start = start > 0 ? start : 0;
    end   = end   > 0 ? end   : 0;
    for (i=start; i>=end; i--) {
        a[i] += c;
        c     = a[i] / 10;
        a[i] %= 10;
    }
    if (c && i >= 0) a[i] = c;
}

static void lnum_to_string(char *str, char *lnum)
{
    int i;
    for (i=0; i<MAX_LNUM_SIZE && !lnum[i]; i++);
    for (   ; i<MAX_LNUM_SIZE; i++) *str++ = lnum[i] + '0';
    *str = '\0';
}

void lnum_multiply(char *result, char *a, char *b)
{
    char *lr = NULL;
    int   nda= strlen(a);
    int   ndb= strlen(b);
    int   i, j;

    lr = calloc(1, MAX_LNUM_SIZE);
    if (!lr) {
        printf("failed to allocate memory !\n");
        goto exit;
    }

    if (nda < ndb) { // swap a & b
        char *p;
        int   t;
        p = a; t   = nda;
        a = b; nda = ndb;
        b = p; ndb = t;
    }

    for (i=0; i<ndb; i++) {
        for (j=0; j<nda; j++) {
            if (MAX_LNUM_SIZE - i - j - 1 >= 0) {
                lr[MAX_LNUM_SIZE - i - j - 1] += (a[nda-j-1] - '0') * (b[ndb-i-1] - '0');
            }
        }
        lnum_carry(lr, MAX_LNUM_SIZE - i - 1, MAX_LNUM_SIZE - i - j);
    }

    lnum_to_string(result, lr);

exit:
    if (lr) free(lr);
}

#if 1
int main(int argc, char *argv[])
{
    char result[MAX_LNUM_SIZE+1] = {0};
    if (argc < 3) {
        printf("large number multiply program v1.0\n");
        printf("written by rockcarry@\n");
        printf("usage: multiply 123 456\n");
        return 0;
    }
    lnum_multiply(result, argv[1], argv[2]);
    printf("%s * %s = %s\n", argv[1], argv[2], result);
}
#endif



[此贴子已经被作者于2016-10-25 13:51编辑过]

2016-10-25 12:11
sunchao16
Rank: 1
等 级:新手上路
帖 子:12
专家分:0
注 册:2016-10-24
收藏
得分:0 
回复 6楼 word123
因为这个题有点变态,有代码吗?我看看咋写
2016-10-26 10:49
word123
Rank: 10Rank: 10Rank: 10
等 级:贵宾
威 望:13
帖 子:333
专家分:1622
注 册:2014-4-5
收藏
得分:0 
就楼上他们有发代码啊,看下11楼的,但我的编译器编译报错,所以我改了点,应该是我说的第二种方法
#include <stdio.h>
#include <string.h>

char* multiply( const char* a, const char* b, char *c)
{
    const size_t alen = strlen(a);
    const size_t blen = strlen(b);
    for( size_t ai=0; ai!=alen; ++ai )
    {
        unsigned carry = 0;
        for( size_t bi=0; bi!=blen; ++bi )
        {
            carry += c[200000-ai-bi-1] + (a[alen-ai-1]-'0')*(b[blen-bi-1]-'0');
            c[200000-ai-bi-1] = carry % 10;
            carry /= 10;
        }
        if( carry != 0 )
            c[200000-ai-blen-1] = carry;
    }

    char* p = &c[200000-1];
    for( size_t i=0; i!=200000; ++i )
    {
        c[i] += '0';
        if( p==&c[200000-1] && c[i]!='0' )
            p = c+i;
    }
    return p;
}

int main( void )
{
    char a[100001], b[100001], c[200001]={0};
    scanf( "%s%s", a, b );
    printf( "%s\n", multiply(a,b,c) );

    return 0;
}
2016-10-26 12:24
sunchao16
Rank: 1
等 级:新手上路
帖 子:12
专家分:0
注 册:2016-10-24
收藏
得分:0 
我用Dev-c++验证上面所有代码,全都报错,这是咋了
2016-10-26 17:58
sunchao16
Rank: 1
等 级:新手上路
帖 子:12
专家分:0
注 册:2016-10-24
收藏
得分:0 
回复 15楼 sunchao16
我用Dev-c++验证上面所有代码,全都报错,这是咋了
2016-10-26 18:01
sunchao16
Rank: 1
等 级:新手上路
帖 子:12
专家分:0
注 册:2016-10-24
收藏
得分:0 
回复 11楼 rjsp
我用Dev-c++验证了代码,报错
2016-10-26 18:04
sunchao16
Rank: 1
等 级:新手上路
帖 子:12
专家分:0
注 册:2016-10-24
收藏
得分:0 
回复 11楼 rjsp
我用Dev-c++验证了代码,报错
2016-10-26 18:04
快速回复:c语言第一次接触高精度乘法,求代码。
数据加载中...
 
   



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

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