您的位置:首页 > 其它

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

2016-04-12 22:21 519 查看
分治算法:

指将一个规模为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
);
}
printf( "\n" );
free( a ); /* 释放 a 指向的内存空间*/
free( b ); /* 释放 b 指向的内存空间*/
free( result ); /* 释放 result 指向的内存空间*/
system( "PAUSE" );
return(0);
}


运行结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: