C 语言 实现大数相乘问题(包括正、负整数,另外还附有详细注释)

来源:互联网 发布:合肥软件开发 编辑:程序博客网 时间:2024/06/05 17:43

分治算法:

指将一个规模为N的问题分解为 K 个规模较小的子问题,这些子问题相互独立与原问题性质相同。只要求出子问题的解,就可得到原问题的解。

解题思路:

(1)分解,将要解决的问题划分为若干个规模较小的同类问题。

(2)求解,当子问题划分的足够小时,用较简单的方法解决。

(3)合并,按原问题的要求,将子问题的解逐层合并构成原问题的解。

PS:子问题之间不包含公共的子问题。此特征涉及分治法的效率问题,如果各子问题是不独立的,则分治法要做许多不必要的工作,重复地解公共子问题,此时虽然可用分治法,但一般用 动态规划法较好


算法应用举例:

问题描述:实现大数相乘,即计算两个大数的积。 解题思路:拆、逐位相乘求和

#include <stdio.h>#include <stdlib.h>#include <malloc.h>#include <string.h>char *result = '\0';int pr = 1;void getFill( char *a, char *b, int ia, int ja, int ib, int jb, int tbool, int move ){    int r, m, n, s, j, t;    char *stack;    m = a[ia] - 48; /* 字符转换为数字 */    if ( tbool ) /* 直接从结果数组的标志位填入,这里用了堆栈思想 */    {        r = (jb - ib > ja - ia) ? (jb - ib) : (ja - ia); // 计算那个位数大        stack = (char *) malloc( r + 4 );        for ( r = j = 0, s = jb; s >= ib; r++, s-- )        {            n = b[s] - 48; // 从低位开始计算            stack[r] = (m * n + j) % 10; // 存储余数            j = (m * n + j) / 10; // 存储进位        }        if ( j ) // 如果有进位,则存储到栈顶        {            stack[r] = j;            r++;        }        for ( r--; r >= 0; r--, pr++ )            result[pr] = stack[r];        free( stack ); // 释放栈空间        for ( move = move + pr; pr < move; pr++ )            result[pr] = '\0'; // 在字符数组后面添加结束符    }    else    /* 与结果的某几位相加,这里不改变标志位pr的值 */    {        r = pr - move - 1;        for ( s = jb, j = 0; s >= ib; r--, s-- )        {            n = b[s] - 48;            t = m * n + j + result[r];            result[r] = t % 10;            j = t / 10;        }        for(; j; r--)        {            t = j + result[r];            result[r] = t%10;            j = t/10;        }    }}/* 注意: ia,ib表示从数字的第几位开始计算,正:第0位,负:第1位*/int get( char *a, char *b, int ia, int ja, int ib, int jb, int t, int move ){    int m, n, s, j;    if ( ia == ja ) // 其中一个数位数为0 或 1,直接计算    {        getFill( a, b, ia, ja, ib, jb, t, move );        return(1);    }    else if ( ib == jb ) // 其中一个数位数为0 或 1,直接计算    {        getFill( b, a, ib, jb, ia, ja, t, move );        return(1);    }    else    {        m = (ja + ia) / 2;        n = (jb + ib) / 2;        s = ja - m;        j = jb - n;        get( a, b, ia, m, ib, n,t,s + j + move );        get( a, b, ia, m, n + 1, jb,0,s + move );        get( a, b, m + 1, ja, ib, n,0,j + move );        get( a, b, m + 1, ja, n + 1, jb, 0,0 + move );    }    return(0);}int main(){    char *a, *b;    int n, flag;    a = (char *) malloc( 1000 ); // 申请1000个字符型存储单元    b = (char *) malloc( 1000 ); // 申请1000个字符型存储单元    printf( "The program will computer a*b\n" );    printf( "Enter a b:" );    scanf( "%s %s", a, b );    result = (char *) malloc( strlen( a ) + strlen( b ) + 2 ); /* 存储读入字符串的长度*/    flag = pr = 1;    result[0] = '\0';    if ( a[0] == '-' && b[0] == '-' ) /* 2个数都是负数*/        get( a, b, 1, strlen( a ) - 1, 1, strlen( b ) - 1, 1, 0 );    if ( a[0] == '-' && b[0] != '-' ) /* 2个数一正一负*/    {        flag = 0;        get( a, b, 1, strlen( a ) - 1, 0, strlen( b ) - 1, 1, 0 );    }    if ( a[0] != '-' && b[0] == '-' ) /* 2个数一正一负*/    {        flag = 0;        get( a, b, 0, strlen( a ) - 1, 1, strlen( b ) - 1, 1, 0 );    }    if ( a[0] != '-' && b[0] != '-' ) /* 2个正数*/    {        get( a, b, 0, strlen( a ) - 1, 0, strlen( b ) - 1, 1, 0 );    }    if ( !flag ) /* 正负标识位 */        printf( "-" );    if ( result[0] )        printf( "%d", result[0] );    for ( n = 1; n < pr; n++ )    {        printf( "%d", result[n] );    }    printf( "\n" );    free( a ); /* 释放 a 指向的内存空间*/    free( b ); /* 释放 b 指向的内存空间*/    free( result ); /* 释放 result 指向的内存空间*/    system( "PAUSE" );    return(0);}

运行结果:



2 0
原创粉丝点击