您的位置:首页 > 其它

整数高精度运算的库(加法,减法,乘法,除法,取模)

2011-05-28 18:26 423 查看
这几天开始做些ACM的Online Judge题目,遇到了个数据范围有10^100的题目,原题 是求两个整数的最小公倍数,没用高精写好算法后发现需要的运算类型比较多,基本除了加法没用到其他的都要,于是乎决定写这么个库,也能方便以后刷刷水题,^_^。
这是前面的声明部分,MAX_SIZE_MLONG为大整数的最大长度,将char*定义为mlong型也方便以后的代码书写及可读性。 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE_MLONG 101
typedef char* mlong;

下面是除了基本运算之外的功能函数:/* 分配MAX_SIZE_MLONG长度的字符指针 */
mlong new_mlong(void)
{
return (mlong)malloc(sizeof(char) * (MAX_SIZE_MLONG + 1));
}

/* 比较两数大小,a>b返回正,a<b时返回负,a=b时返回0 */
int mcmp(mlong a, mlong b)
{
if (strlen(a) == strlen(b))
return strcmp(a, b);
else return (strlen(a) - strlen(b));
}

/* 将形如0001或-0001前的0去掉 */
mlong mtrim(mlong m)
{
int i;
if ((m[0] == '-' && m[1] != '0') || (m[0] != '-' && m[0] != '0') ||
(m[0] == '-' && strlen(m) == 2) || (m[0] != '-' && strlen(m) == 1)) return m;
if (m[0] == '-') i = 1;
else i = 0;
for (; i < strlen(m) - 1; i++) {
if (m[i] != '0') break;
}
if (m[0] == '-') strcpy(m+1, m+i);
else strcpy(m, m+i);
return m;
}

/* 将整数逆序,当整数前有多余的0时自动去掉 */
void mreverse(mlong m)
{
int i,j;
char t;
for (i = 0, j = strlen(m) - 1; i < j; i++, j--) {
t = m[i];
m[i] = m[j];
m[j] = t;
}
m = mtrim(m);
}

减法运算:
/* a-b
* 依赖:mreverse()
*/

mlong msub(mlong a, mlong b)
{
mlong stmp;
mlong r;
char c;
int i, h;
int la, lb;
int sign = mcmp(a, b);
if (sign < 0) {
stmp = a;
a = b;
b = stmp;
}

h = 0;
la = strlen(a);
lb = strlen(b);
r = (mlong)malloc(sizeof(char) * (la + 1));
for (i = 0; i < la; i++) {
if (i < lb){
c = b[lb-1-i];
}
else{
c = '0';
}
if (h == 1 && (a[la-1-i] - 1)< c)
r[i] = a[la-1-i] - c + 9 + '0';
else if (h == 1) {
r[i] = a[la-1-i] - c - 1 + '0';
h = 0;
}
else if (a[la-1-i] < c) {
r[i] = a[la-1-i] - c + 10 + '0';
h = 1;
}
else {
r[i] = a[la-1-i] - c + '0';
}

}
if (sign < 0) {
r[i++] = '-';
b = a;
a = stmp;
}
r[i] = '\0';
mreverse(r);
return r;
}

加法运算: /* a+b
* 可以实现负数加法
* 依赖:new_mlong(), mreverse(), msub(), msub()
*/
mlong madd(mlong a, mlong b)
{
int i, h;
int la, lb, l;
int ia, ib;
mlong r = new_mlong();
if (a[0] == '-' && b[0] != '-') return msub(b, a+1);
else if (a[0] != '-' && b[0] == '-') return msub(a, b+1);
else if (a[0] == '-' && b[0] == '-') {
r[0] = '-';
strcpy(r+1, madd(a+1, b+1));
}
else{
la = strlen(a);
lb = strlen(b);
l = (la > lb) ? la : lb;
h = 0;
for (i = 0; i < l; i++) {
ia = ((la-1-i) < 0) ? 0 : a[la-1-i] - '0';
ib = ((lb-1-i) < 0) ? 0 : b[lb-1-i] - '0';
r[i] = (ia + ib + h) % 10 + +'0';
h = (ia + ib + h) / 10;
}
if(h) r[i++] = '1';
r[i] = '\0';
mreverse(r);
}
return r;
}

乘法运算:

/* a*b
* 依赖:MAX_SIZE_MLONG, mreverse()
*/
mlong mmul(mlong a, mlong b){
int i, j;
int h;
int m;
mlong r = (mlong)malloc(sizeof(char)*(MAX_SIZE_MLONG * 2 + 1));
memset(r, '0', MAX_SIZE_MLONG * 2 + 1);
int la = strlen(a);
int lb = strlen(b);
for (j = 0;j < lb; j++) {
h = 0;
if (b[lb-j-1] == '0') continue;
for (i = 0; i < la; i++) {
m = (b[lb-j-1]-'0') * (a[la-i-1]-'0') + r[i+j]-'0' + h;
r[i+j] = m % 10 + '0';
h = m / 10;
}
if (h){
r[la+j] = '0' + h;
if (j == lb-1) r[la+j+1] = '\0';
}
else if (j == lb-1) r[la+j] = '\0';
}
mreverse(r);
return r;
}

除法运算:
/* a/b
* 依赖:mtrim(), mcmp(), mmul(), msub()
*/
mlong mdiv(mlong a, mlong b)
{
int la, l;
int i, j;
mlong res, rem, h, mi, mii;
la = strlen(a);
res = (mlong)malloc(sizeof(char) * (la+1));

if (mcmp(a, b) < 0) {
res = realloc(res, sizeof(char)*2);
strcpy(res, "0");
return res;
}
rem = (mlong)malloc(sizeof(char) * 2);
h = (mlong)malloc(sizeof(char) * (la+1));
mi = (mlong)malloc(sizeof(char) * 2);
mii = (mlong)malloc(sizeof(char) * 2);
strcpy(mi, "0");
strcpy(mii, "1");
strcpy(rem, "0");
for (i = 0; i < la; i++) {
strcpy(h, rem);
l = strlen(h);
h[l] = a[i];
h[l+1] = '\0';
h = mtrim(h);
for (j = 0; j <= 9; j++) {
mi[0] = '0' + j;
mii[0] = '0' + j + 1;
if ((j == 9) || (mcmp(h, mmul(mii, b)) < 0)) {
free(rem);
rem = msub(h, mmul(mi, b));
res[i] = j + '0';
break;
}
}
}
res[i] = '\0';
mtrim(res);
return res;

}

取模运算:
/* a%b
* 依赖:mtrim(), mcmp(), mmul(), msub()
*/
mlong mmod(mlong a, mlong b)
{
int la, l;
int i, j;
mlong rem, h, mi, mii;
la = strlen(a);
if (mcmp(a, b) < 0) {
return a;
}
rem = (mlong)malloc(sizeof(char) * 2);
h = (mlong)malloc(sizeof(char) * (la+1));
mi = (mlong)malloc(sizeof(char) * 2);
mii = (mlong)malloc(sizeof(char) * 2);
strcpy(mi, "0");
strcpy(mii, "1");
strcpy(rem, "0");
for (i = 0; i < la; i++) {
strcpy(h, rem);
l = strlen(h);
h[l] = a[i];
h[l+1] = '\0';
h = mtrim(h);
for (j = 0; j <= 9; j++) {
mi[0] = '0' + j;
mii[0] = '0' + j + 1;
if ((j == 9) || (mcmp(h, mmul(mii, b)) < 0)) {
free(rem);
rem = msub(h, mmul(mi, b));
break;
}
}
}
return rem;
}
 使用以上函数时需注意的是不能用在负整数上,不过对于相减得到负数的情况结果会有负号。代码还有许多待改进的地方,有建议童鞋以及大神们欢迎提啊。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c 算法
相关文章推荐