大数的除法运算

数学里的除法运算通常写作:
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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值