首页 > 技术文章 > 高精度-除法

h-hg 2018-03-26 12:37 原文

高精度除法的思路

  设a=被除数,b=除数,c=商,lena=a的位数,lenb=b的位数,len=c的位数,A=以b的位数为准的高位
  所谓的高位,举个例子,a=12345,b=110,那么A=123(取前三位)。将A的位数往后移动一位,就是A=1234。
流程图如下

流程图代码(只是方便博主修改)

st=>start: begin
lencmp=>condition: lena < lenb ?
result1=>inputoutput: c = 0
get_A=>operation: 以b的位数为准,取a的高位A
A_gte_b=>condition: A ≥ b
lena_e_lenb=>condition: lena = lenb ?
minus=>subroutine: 不断用A-b,直到A小于b,减去的次数=商的最高位
move=>operation: 将A的位数往后移动一位
can'tmove=>condition: 不能往后移动 ?
result2=>inputoutput: 得出结果
A_lt_b=>condition: A < b
getNextBit=>operation: 得到商的下一高位0
len1=>operation: len = lena - lenb + 1
len2=>operation: len = lena - lenb,并将A往后移动一位
e=>end
st->lencmp
lencmp(yes,right)->result1
lencmp(no)->get_A->A_gte_b
A_gte_b(no)->lena_e_lenb
lena_e_lenb(yes,right)->result1
lena_e_lenb(no)->len2->minus
A_gte_b(yes)->len1->minus
minus->move->can'tmove
can'tmove(yes)->result2
can'tmove(no)->A_lt_b
A_lt_b(yes,right)->getNextBit->move
A_lt_b(no)->minus

c++代码

int unsign_divide(const int *a,int lena,const int *b,int lenb,int *&quotient)
{
	if(lena < lenb)
	{
		quotient = new int[1]{0};
		return 1;
	}
    int currentBit = lena - lenb;//商上的第一个数对应a的下标
	int len;
	if(divide_gte(a,lena,currentBit,b,lenb))
        len = currentBit + 1;
    else if(lena == lenb)//lena == lenb && a < b
    {
        quotient = new int[1]{0};
        return 1;
    }
    else//lena > lenb && a前面大于b
    {
        len = currentBit;
        --currentBit;
    }
	quotient = new int[len];
	//copy
	int *A = new int[lena];
	memcpy(A,a,sizeof(int)*lena);
	int sub = len -1;
	while(currentBit >= 0)
	{
		quotient[sub] = 0;
		do
		{   //minus
            int Asub = currentBit;
            for(int i =0;i < lenb;++i)
                if(A[Asub] >= b[i])
                    A[Asub++] -= b[i];
                else
                {
                    A[Asub] += bitmax - b[i];
                    --A[Asub++];
                }
            while(Asub < lena && A[Asub] < 0)
            {
                A[Asub] += bitmax;
                --A[++Asub];
            }
			++quotient[sub];
		}while(divide_gte(A,lena,currentBit,b,lenb));
		if(--sub,--currentBit < 0)
			break;
		while(!divide_gte(A,lena,currentBit,b,lenb))
		{
			quotient[sub] = 0;
			if(--sub,--currentBit < 0)
				break;
		}
	}
	delete[]A;
	return len;
}

推荐阅读