大数的运算

来源:互联网 发布:金扎软件 编辑:程序博客网 时间:2024/05/22 15:25

大数运算指的是对C语言中那些大到超出表示范围的数的运算,比如9999999999999999999999999999999+9999999999999999999999999。C语言中无法将这么大的一个数存储到变量中,这里就要用到大数的运算了。

大数加法:
思路很简单,就是把这个“大数”以字符串的形式存入数组中,然后倒序放入整型数组便于逐步相加。附上代码如下

void add(char*num1, char*num2){    int intnum1[MAX] = { 0 };    int intnum2[MAX] = { 0 };    int i = 0, j = 0;    int len1 = strlen(num1);    int len2 = strlen(num2);    int len = len1 > len2 ? len1 : len2;    for (i = len1 - 1; i >= 0; i--)//将数字逆序存入整型数组中,便于相加    {        intnum1[j++] = num1[i]-48;    }    j = 0;    i = 0;    for (i = len2 - 1; i >= 0; i--)    {        intnum2[j++] = num2[i]-48;    }    for (i = 0; i < len+1; i++)//逐步相加    {        intnum1[i] += intnum2[i];        if (intnum1[i]>9)        {            intnum1[i] -= 10;            intnum1[i + 1]++;//有进位,下一位加1        }    }    for (i = len; i >= 0; i--)    {        if (i == len&&intnum1[i] == 0)            ;        else            printf("%d", intnum1[i]);    }}

大数减法:
减法的思路和加法类似。也是将俩数存入到字符数组中,然后倒序放入整型数组便于逐步相减。但区别于加法的一点是减法需要事先判断好那个数字比较大,由较大数减去较小数。最后输出的时候要注意正负号,代码如下:

void sub(char*num1, char*num2){    int intnum1[MAX] = { 0 };    int intnum2[MAX] = { 0 };    int i = 0, j = 0;    int len1 = strlen(num1);    int len2 = strlen(num2);    int len = len1 > len2 ? len1 : len2;    /*判断哪个数比较大*/    char*biggersize = judgesize(num1, num2);    for (i = len1 - 1; i >= 0; i--)//倒序存入整型数组中    {        intnum1[j++] = num1[i] - 48;    }    j = 0;    i = 0;    for (i = len2 - 1; i >= 0; i--)    {        intnum2[j++] = num2[i] - 48;    }    if (biggersize==num1)    for (i = 0; i < len; i++)//逐步相减    {        intnum1[i] -= intnum2[i];        if (intnum1[i] < 0)        {            intnum1[i] += 10;            intnum1[i + 1]--;        }    }    else    for (i = 0; i < len; i++)    {        intnum2[i] -= intnum1[i];        if (intnum2[i]<0)        {            intnum2[i] += 10;            intnum2[i + 1]--;        }    }    if (biggersize==num1)    {        for (i = len-1; i >= 0; i--)        {            if (i == len-1&&intnum1[i] == 0)                ;            else                printf("%d", intnum1[i]);        }    }    else    {        printf("-");        for (i = len-1; i >= 0; i--)        {            if (i == len-1&&intnum2[i] == 0)                ;            else                printf("%d", intnum2[i]);        }    }}

大数的乘法:
相对于前两者,乘法稍微复杂一些。乘法的实现主要基于加法:把一个乘数每位上的数取下来分别与另一个数相乘(这里要注意相乘的结果的大小,比如把十位上的数取下来与另一乘数进行运算,要记得在后面补上一个0),然后把相乘的结果加起来就是结果。
代码如下:

void mul(char*num1, char*num2){    int intnum1[MAX] = { 0 };    int intnum2[MAX] = { 0 };    int pt[MAX] = { 0 };    int num[MAX] = { 0 };    int i = 0, j = 0, k = 0, t = 0;    int tenpos = 0;//俩个位数相乘的值得十位上的数    int len1 = strlen(num1);    int len2 = strlen(num2);    for (i = len1 - 1; i >= 0; i--)    {        intnum1[j++] = num1[i] - 48;    }    j = 0;    i = 0;    for (i = len2 - 1; i >= 0; i--)    {        intnum2[j++] = num2[i] - 48;    }    for (i = 0; i < len2; i++)//取intnum2上的每位来相乘    {    /*intnum2上的每位与intnum1上存的数相乘*/        for (j = 0; j < len1+1; j++)        {        /*t的作用是确保每一步相乘后,末尾0的个数*/            pt[j+t] = intnum2[i] * intnum1[j]+tenpos;            tenpos = 0;            if (pt[j+t]>9)//记录进位            {                tenpos = pt[j+t] / 10;                pt[j+t] %= 10;            }        }        /*相乘的结果进行加法运算(大数加法)*/        for (k = 0; k < len1+t+1; k++)        {            num[k] += pt[k];            if (num[k]>9)            {                num[k] -= 10;                num[k + 1]++;            }        }        t++;        memset(pt, 0, sizeof(int)*len1);    }    for (i = MAX - 1; i >= 0;i--)//寻找相乘结果的第一位数    if (num[i] != 0)    {        j = i;        break;    }    for (i = j; i >= 0;i--)        printf("%d", num[i]);}

大数除法:
思路很简单,但是实现起来很复杂。这里通过例子来说明:
假设a={2 4 2 3 1},b={2 3},结果result={0 0 0 0 0}:
先取a[0]a[1]即24,减去b一次,得a={0 1 2 3 1},result={0 1 0 0 0};
再取a[1]a[2]即12,发现它小于b,则多取一位,取a[1]a[2]a[3]即123,减b五次,得a={0 0 0 8 1},result={0 1 0 5 0};
再取a[3]a[4]即81,减b三次,得a={0 0 0 1 2},result={0 1 0 5 3}。

/*比较除数与被除数上相应位的大小*/int judgedivisorsize(int*num1, int*num2,int lendivisor,int t){    int i = 0;    if (t == 1)        return 1;    for (i = 0; i < lendivisor; i++)    {        if (num1[i]>num2[i])//被除数大于除数返回1            return 1;        else if (num1[i] < num2[i])//小于返回-1            return -1;        else            ;    }    return 1;//相等的时候返回1}void div(char*num1, char*num2){    int intnum1[MAX] = { 0 };    int intnum2[MAX] = { 0 };    char result[MAX] = { 0 };//记录商的数组    int i = 0, j = 0, k = 0, t = 0;    int len1 = strlen(num1);    int len2 = strlen(num2);    int lenresult = 0;    if (num2 == judgesize(num1, num2))    {        printf("结果=0\n");        printf("余数=%s", num2);        return;    }    for (i = 0; i < len1 ; i++)    {        intnum1[i] = num1[i] - 48;    }    for (i = 0; i < len2; i++)    {        intnum2[i] = num2[i] - 48;    }    for (i = 0; i <= len1 - len2; i++)    {        if (judgedivisorsize(intnum1 + i, intnum2, len2, t) >= 0)        {        /*t的作用:使上一轮比较的数的首位留到下一轮比较(如果首位不为0的话)。*/            while (judgedivisorsize(intnum1 + i, intnum2, len2, t) >= 0)            {                for (j = len2 - 1; j >= 0; j--)                {                    intnum1[j + i] -= intnum2[j];                    if (intnum1[j + i] < 0)                    {                        intnum1[j + i] += 10;                        intnum1[j + i - 1]--;                    }                    /*当上一轮的首位为0的时候要即使调整,便于正确判断本轮比较的数的大小*/                    if (intnum1[i - 1] == 0)                        t = 0;                }                result[len2 + i - 1]++;            }            /*当一轮比较结束,例如24563/13,24减去13余下11,不够减,intnum1首位的1要留到下一轮去比较,设置t为1*/            /*当intnum1首位为0的时候,并不需要留到下一轮*/            for (k = i; k < len2 + i; k++)            {                if (intnum1[i] == 0)                    break;                t = 1;            }        }    else        {        /*11234/12,11小于12,不够减,设置t为1,使得下一次112与12比较。*/            if (intnum1[i] != 0)                t = 1;            if (result[len2 + i - 1] == '\0')            result[len2 + i - 1] = '0';        }    }    printf("商=");    lenresult = result[len1 - 1] == 0 ? len1 - 1 : len1;    for (i = 0; i < lenresult; i++)    {        if (result[i] != '0')            result[i] += '0';    }    printf("%s\n余数=", result);    j = 0;    for (i = len1 - len2; i < len1; i++)    {        if (intnum1[i] != 0)        {            j = i;            break;        }    }    for (i = j; i < len1; i++)        printf("%d", intnum1[i]);    printf("\n");}
0 0
原创粉丝点击