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