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

分治算法:

指将一个规模为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);
}

运行结果:

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


    原文作者:大整数乘法问题
    原文地址: https://blog.csdn.net/qq_24452475/article/details/51137328
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞