C 语言 实现大数相乘问题(包括正、负整数,另外还附有详细注释)
2016-04-12 22:21
567 查看
分治算法:
指将一个规模为N的问题分解为 K 个规模较小的子问题,这些子问题相互独立与原问题性质相同。只要求出子问题的解,就可得到原问题的解。
解题思路:
(1)分解,将要解决的问题划分为若干个规模较小的同类问题。
(2)求解,当子问题划分的足够小时,用较简单的方法解决。
(3)合并,按原问题的要求,将子问题的解逐层合并构成原问题的解。
PS:子问题之间不包含公共的子问题。此特征涉及分治法的效率问题,如果各子问题是不独立的,则分治法要做许多不必要的工作,重复地解公共子问题,此时虽然可用分治法,但一般用 动态规划法较好。
算法应用举例:
问题描述:实现大数相乘,即计算两个大数的积。 解题思路:拆、逐位相乘求和
运行结果:
指将一个规模为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); }
运行结果:
相关文章推荐
- svn 回滚old revision到head revision
- 欢迎使用CSDN-markdown编辑器
- HDOJ 1280 前m大的数
- bzoj 4523 [Cqoi2016]路由表
- 求sin x
- 想收车回家怎么办?输入目的地,顺路接单回家!
- 20135320赵瀚青LINUX第四章读书笔记
- MySQL调优
- Mstar 编译器的搭建
- strstr和KMP
- OpenJudge(1221)——UNIMODAL PALINDROMIC DECOMPOSITIONS
- ffmpeg学习(二) 通过rtsp获取H264裸流并保存到mp4文件
- GraphFrames介绍
- 19. Remove Nth Node From End of List
- ZOJ 2853 Evolution【矩阵快速幂】
- ArcGIS Desktop python Add-in 创建一个插件
- iOS学习笔记21-推送证书与秘钥申请
- 国产手机份额再高 也不可能撼动苹果地位
- Leetcode Remove Duplicates from Sorted List 83
- 最简单的基于FFmpeg的推流器(以推送RTMP为例)