【算法】大数四则运算

这篇博客主要探讨了如何实现大数的四则运算,作者分享了在完成作业过程中遇到的不同算法,包括3位数运算、移位运算以及仿手工运算。尽管参考Python的大数运算可能是最佳选择,但作者选择了实现简单易用的仿手工运算算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在写大数四则运算的作业,发现网上有很多相关的算法,有3位作四则运算的,也有仿造计算机做移位运算的,当然,有仿照手工运算的算法。

最好的算法应该可以参考python的大数运算,不过本人还是自己实现仿手工运算的算法:好用、简单。


/*****************************************************************
 *
 *  Big number add/minus/multiply/divide
 *  Copyright: Free
 *  Author: Hou Hongwei
 *
 *
 ****************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void reverse(char *in, char *out, int len)
{
    int i, j;
    i = 0;
    j = len;

    while (i < len && j >= 0)
    {
        out[i++] = in[--j];
    }
    out[len] = '\0';
    //printf("reverse from %s to %s\n", in, out);
}

void trim(char *inout, int *len)
{
    int i;
    i = (*len) - 1;
    while (inout[i] == '0')
    {
        if(i > 0) inout[i] = 0;
        i--;
    }
    
    (*len) = i + 1;

}

int is_bigger(char *x, char *y)
{
    int i, j;
    int xlen, ylen;

    xlen = strlen(x);
    ylen = strlen(y);

    //Remove '0' in bigger space
    trim(x, &xlen);
    trim(y, &ylen);

    if (xlen > ylen)
    {
        return 1;
    }

    if (xlen == ylen)
    {
        for (i = xlen -1; i >= 0; i--)
        {
            if(x[i] > y[i]) return 1;
            else if (x[i] < y[i]) return 0;
        }
    }

    return 0;
}
/**************************************
 *
 *  out len should bigger than
 *  x len and y len, and even
 *  1 more than the biggest
 *
 * ***********************************
 */
int add(char *x, char *y, char *out)
{
    int xlen, ylen, outlen;
    int i, j;
    
    xlen = strlen(x);
    ylen = strlen(y);
   
    j = (xlen > ylen ? ylen : xlen);
    for (i = 0; i < j; i++)
    {
        out[i] = (x[i] -'0') + (y[i] - '0');

    }

    j = (xlen > ylen ? xlen : ylen);
    for (; i < j; i++)
    {
        out[i] = ((xlen > ylen ? x[i] : y[i]) - '0');

    }

    out[j] = 0;
    for (i = 0; i < j; i++)
    {
        if (out[i] >= 10)
        {
            out[i+1] += 1;
            out[i] -= 10;
        }
        out[i] += '0';
    }

    if(out[i] > 0)  out[i] += '0';

    //printf("out: %s\n", out);

}


/**************************************
 *
 *  This function assume that
 *  X is always bigger than Y
 *
 * ***********************************
 */
int _minus(char *x, char *y, char *out)
{
    int xlen, ylen, outlen;
    int i, j;
    int mark_ne;
    
    xlen = strlen(x);
    ylen = strlen(y);
    outlen = strlen(out);

    memset(out, 0, outlen);
    //Check out len
    for (i = 0; i < ylen; i++)
    {
        out[i] = (x[i] -'0') - (y[i] - '0');

    }

    for (; i < xlen; i++)
    {
        out[i] = x[i] - '0';
    }

    for (i = 0; i < xlen - 1; i++)
    {
        if (out[i] < 0)
        {
            out[i+1] -= 1;
            out[i] += 10;
        }
        out[i] += '0';
    }

    if(out[i] > 0)
    {
        out[i] += '0';
    }
    else if (out[i] == 0)   //The biggest bit is 0
    {
        while (out[--i] == '0' && i >= 0)
        {
            out[i] = 0;
        }
        if(i == -1)
        {
            out[0] = '0';
        }
    }

}

int minus(char *x, char *y, char *out)
{
    int outlen, res;
    //Check if Y > X, if it is mark '-'
    if (is_bigger(y, x))
    {
        res = _minus(y, x, out);
        outlen = strlen(out);
        // Add flag '-'
        out[outlen] = '-';
        return res;
    }

    return _minus(x, y, out);
}

void multiply(char *x, char *y, char *out)
{
    int xlen, ylen, outlen;
    int i, j;
    
    xlen = strlen(x);
    ylen = strlen(y);

    for (i = 0; i < xlen; i++)
    {
        for (j = 0; j < ylen; j++)
        {
            out[i+j] += (x[i]-'0') * (y[j]-'0');
        }
    }

    for (i = 0; i < (xlen + ylen - 1); i++)
    {
        if (out[i] >= 10)
        {
            out[i+1] += out[i]/10;
            out[i] = out[i]%10;
        }
        out[i] += '0';
    }

    if(out[i] > 0)  out[i] += '0';
    
}

int divide(char *x, char *y, char *quotient, char *remainder)
{
    int xlen, ylen;
    int qlen, rlen;
    char *tmp_x, *tmp_out;
    int sum = 0;
    int i, j, k;

    xlen = strlen(x);
    ylen = strlen(y);

    // If Y > X, remainder is X and quotient is 0
    if (is_bigger(y, x))
    {
        quotient[0] = '0';
        strncpy(remainder, x, xlen);
        return 0;
    }

    //If X > Y
    //FIXME:
    qlen = xlen - ylen + 1;
    rlen = ylen;
    tmp_x = (char *)malloc(ylen + 1);
    tmp_out = (char *)malloc(ylen + 1);

    k = qlen - 1;

    strncpy(tmp_x, &x[xlen - ylen], ylen);
    memset(quotient, 0, qlen);
    for (i = xlen -ylen; i >= 0; i--)
    {
        memset(tmp_out, '\0', strlen(tmp_out));
        strncpy(tmp_out, tmp_x, strlen(tmp_x));
        // tmp_x >= y
        if (!is_bigger(y, tmp_out))
        {
            do
            {
                memset(tmp_x, '\0', strlen(tmp_x));
                strncpy(tmp_x, tmp_out, strlen(tmp_out));
                memset(tmp_out, '\0', strlen(tmp_out));
                _minus(tmp_x, y, tmp_out);
                quotient[k] ++;
            }while(!is_bigger(y, tmp_out));  //tmp_out >= y
        }

        if(k > 0)
        {
            memset(tmp_x, 0, strlen(tmp_x));
            tmp_x[0] = x[--k];
            //tmp_x = tmp_out << 1 + x[--k]
            strncat(tmp_x, tmp_out, (strlen(tmp_out) + 1));
        }
        else
        {
            strncpy(remainder, tmp_out, strlen(tmp_out));
            j = strlen(remainder);
            trim(remainder, &j);
            break;
        }
                
    }

    //Filter the 0
    k = qlen - 1;
    while (quotient[k] == 0) 
    {
        k--;
    }
    while (k >= 0)
    {
        quotient[k--] += '0';
    }

    free(tmp_x);
    free(tmp_out);
}

int main(int argc, const char *argv[])
{
    char in1[] = "60000000000000000000000000000000";
    char in2[] = "1234567890";
    char *x, *y, *out1, *out2;
    char *out3, *out4;
    int outlen;

    x = (char *)malloc(sizeof(in1));
    y = (char *)malloc(sizeof(in2));
    outlen = (sizeof(in1) > sizeof(in2) ? sizeof(in1) : sizeof(in2)) + 1;
    out1 = (char *)malloc(outlen);
    out2 = (char *)malloc(outlen);

    reverse(in1, x, strlen(in1));
    //printf("x: %s\n", x);
    reverse(in2, y, strlen(in2));
    //printf("y: %s\n", y);

    add(x, y, out1);
    //printf("out1: %s\n", out1);
    reverse(out1, out2, strlen(out1));
    printf("%s + %s = %s\n", in1, in2, out2);

    minus(x, y, out1);
    //printf("out1: %s, len: %d\n", out1, strlen(out1));
    reverse(out1, out2, strlen(out1));
    printf("%s - %s = %s\n", in1, in2, out2);

    outlen = sizeof(in1) + sizeof(in2);

    out3 = (char *)malloc(outlen);
    out4 = (char *)malloc(outlen);
    multiply(x, y, out3);
    //printf("out3: %s\n", out3);
    reverse(out3, out4, strlen(out3));
    printf("%s * %s = %s\n", in1, in2, out4);

    memset(out1, 0, strlen(out1));
    memset(out2, 0, strlen(out2));
    memset(out3, 0, strlen(out3));
    memset(out4, 0, strlen(out4));
    divide(x, y, out1, out2);
    reverse(out1, out3, strlen(out1));
    reverse(out2, out4, strlen(out2));
    printf("%s / %s = %s mod %s\n", in1, in2, out3, out4);


    free(x);
    free(y);
    free(out1);
    free(out2);
    free(out3);
    free(out4);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值