数学里的除法运算通常写作:
y / x = a …b
如果写成等价的乘法形式,则是:
y = ax + b
这个式子有个性质,就是,如果用100x来代替式中的x, 分成2个式子
y = a1(100x) + y1
y1 = a2 x +b1
就有 a= a1a2的连缀, b= b1。这个性质可以用来分段计算a值。
如果用2进制,写成
y = a0a1a2…an x +b
移项得,
y - a0 (2^n *x) - … - an x = b
这是一个连续减的计算。 a0…an的取值是0或1。在连续减的过程,如果y >= 2^i x 相应的系数就取1,否则就取0。这样的a0a1…an连缀起来就是商a, 最后剩下的y就是余数b。
写成代码就是:
class big {
public:
struct imp {
struct list {
unsigned int val;
struct list *prev;
struct list *next;
};
int n;
list *numbers;
list *rear;
int link;
imp& operator+=(imp &x);
imp& operator-=(imp &x);
imp& operator*=(imp &x);
imp& divas(imp &x);
imp& div(imp &x, imp &r);
imp& div_debug(imp &x, imp &r);
int cmp(imp& x);
imp& operator+(imp &x);
imp& operator-(imp &x);
imp& operator*(imp &x);
void del();
void dup(imp &x);
void free();
};
int sign;
struct imp *data;
public:
big(){sign=0;data=0;}
big(int a[], int n);
big(int num);
big(const big &x);
void neg() { if (data && data->n) sign = !sign; }
~big();
big& operator=(const big &a);
big& operator+=(const big& a);
big& operator-=(const big& a);
big& operator*=(const big& a);
big& operator/=(const big& a);
big& operator%=(const big& a);
big operator+(const big& a);
big operator-(const big& a);
big operator*(const big& a);
big operator/(const big& a);
big operator%(const big& a);
big div(const big& a, big &r);
int tostring(char *s, int n);
int toint();
int cmp(const big &a);
int operator>(const big &a) {return cmp(a)>0;}
int operator<(const big &a) {return cmp(a)<0;}
int operator==(const big &a) {return cmp(a)==0;}
int operator>=(const big &a) {return cmp(a)>=0;}
int operator<=(const big &a) {return cmp(a)<=0;}
int operator!=(const big &a) {
if (this==&a)return 0;
if (!data || !a.data) return 1;
return cmp(a)!=0;
}
big operator-() {big b; b= *this; b.neg(); return b; }
};
big::imp& big::imp::div(imp& x, imp &r)
{
imp d;
imp tab[TABLEN];
int i;
struct list *lp;
struct list *node;
struct list *cache;
int ext;
int sum;
imp &s = *gethead();
s.link=0;
s.n =0;
s.numbers= s.rear=0;
d.numbers=0;
d.dup(x);
d.link=0;
tab[0].numbers=0;
tab[0].dup(d);
for(i=1; i<TABLEN; i++) {
d += d;
tab[i].numbers=0;
tab[i].dup(d);
}
d.del();
ext=0;
lp = numbers;
while (d.n < x.n) {
store_sd:
if (s.n) {
node = getnode();
node->val =0;
node->next =0;
node->prev = s.rear;
s.rear->next = node;
s.rear = node;
++s.n;
}
if (lp==0) goto done;
store_d:
node = getnode();
node->val = lp->val;
if (!d.numbers) {
d.rear= node;
node->prev=0;
node->next= 0;
d.numbers= node;
}
else {
node->prev = d.rear;
node->next = 0;
d.rear->next = node;
d.rear = node;
}
++d.n;
lp = lp->next;
}
if (ext==0) {
switch (d.cmp(x)) {
case 0:
d.del();
sum =1;
goto save;
case -1:
++ext;
goto store_sd;
}
}
else ext=0;
sum=0;
for(i=TABLEN-1; i>=0; i--) {
switch (d.cmp(tab[i])) {
case 0:
sum += (1<<i);
d.del();
goto save;
case 1:
d -= tab[i];
sum += (1<<i);
break;
}
}
save:
node = getnode();
node->val = sum;
if (s.numbers) {
node->prev = s.rear;
node->next =0;
s.rear->next = node;
s.rear = node;
}
else {
node->prev = node->next = 0;
s.numbers= s.rear = node;
}
++s.n;
if (lp) {
if (d.n ==0 && lp->val==0) {
lp = lp->next;
sum = 0;
goto save;
}
goto store_d;
}
done:
for(i=0; i<TABLEN; i++) tab[i].del();
r = d;
return s;
}