zoukankan      html  css  js  c++  java
  • C语言实现大数计算

    所谓大数,就是超过longlong表示的位数。

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    #define BASE (10)
    #define MAX(x, y) ((x) > (y) ? (x) : (y))
    
    typedef struct  bignumber_s
    {
        char sign;
        int len;
        char data[];
    }bignumber_s;
    
    bignumber_s *calc_add(bignumber_s *a, bignumber_s *b);
    bignumber_s *calc_sub(bignumber_s *a, bignumber_s *b);
    
    bignumber_s *make_bignumber_temp(int len, int sign)
    {
        bignumber_s *temp = malloc(sizeof(bignumber_s) + len);
        if (NULL == temp)
        {
            perror("Malloc");
            exit(-1);
        }
        temp->sign = sign;
        temp->len = len;
        memset(temp->data, 0, len);
        return temp;
    }
    
    const char *strip_str(const char *str)
    {
        int i = 0;
        int len = strlen(str);
        for (; i < len - 1 && str[i] == '0'; i++)
        {
            ;
        }
        return str+i;
    }
    
    void fill_data_fromstr(bignumber_s *n, const char *str)
    {
        int i = 0;
        int len = n->len;
        for (; i < len; i++)
        {
            int d = str[len - 1 - i] -'0';
            if (d >= 0 && d <= 9)
            {
                n->data[i] = d;
            }
            else
            {
                fprintf(stderr, "Invalid Number:%s
    ", str);
                exit(-1);
            }
        }
    }
    
    bignumber_s *make_bignumber_fromstr(const char *str)
    {
        int sign = 0;
        if (str[0] == '-')
        {
            sign = 1;
            str++;
        }
    
        const char *striped_str = strip_str(str);
        int len = strlen(striped_str);
        bignumber_s *temp = make_bignumber_temp(len, sign);
        fill_data_fromstr(temp, striped_str);
        return temp;
    }
    
    void print_bignumber(bignumber_s *b)
    {
        int len = b->len;
        char *str = malloc(len+1);
        int i = 0;
    
        for(; i < len; i++)
        {
            str[i] = b->data[len-i-1] + '0';
        }
        str[len] = '';
    
        fprintf(stdout, "%s%s
    ", b->sign == 1 ? "-":"", strip_str(str));
        free(str);
    }
    
    void usage(const char *s)
    {
        fprintf(stderr, "Usage:%s number +-x/ number2.
    ", s);
        exit(-1);
    }
    
    void add_impl(bignumber_s *a, bignumber_s *b, bignumber_s *r)
    {
        int i = 0;
        char carry = 0;
        int len = r->len;
        for(; i < len; i++)
        {
            if (i < a->len)
            {
                carry += a->data[i];
            }
            if (i < b->len)
            {
                carry += b->data[i];
            }
            r->data[i] = carry % BASE;
            carry /= BASE;
        }
    }
    
    bignumber_s *calc_add(bignumber_s *a, bignumber_s *b)
    {
        if (a->sign == b->sign)
        {
            int len = MAX(a->len, b->len) + 1;
            bignumber_s *result = make_bignumber_temp(len, a->sign);
            add_impl(a, b, result);
            return result;
        }
        else if (a->sign == 0 && b->sign == 1)
        {
            b->sign = 0;
            return  calc_sub(a, b);
        }
        else if (a->sign == 1 && b->sign == 0)
        {
            a->sign = 0;
            return calc_sub(b, a);
        } 
    }
    
    void sub_impl(bignumber_s *a, bignumber_s *b, bignumber_s *r)
    {
        int i = 0;
        int borrow = 0;
        int len = r->len;
        int temp = 0;
        for (i = 0; i < len; i++)
        {
            temp = a->data[i] + BASE - borrow - ((i < b->len) ? b->data[i]:0);
            r->data[i] = temp % BASE;
            borrow = temp/BASE ? 0 : 1;
        }
    }
    
    int valid_len(bignumber_s *a)
    {
        int len = a->len;
        int i = len - 1;
        for (i = len - 1; i >= 0; i--)
        {
            if(a->data[i] == 0)
            {
                len--;
            }
            else
            {
                break;
            }        
        }
        return len;
    }
    
    int cmp(bignumber_s *a, bignumber_s *b)
    {
        if (a->sign == 0 && b->sign == 1)
        {
            return 1;
        }
        if (a->sign == 1 && b->sign == 0)
        {
            return -1;
        }
    
        int sign = a->sign;
        int alen = valid_len(a);
        int blen = valid_len(b);
        
        if (alen > blen)
        {
            return (sign == 1 ? -1 : 1);
        }
        else if (alen < blen)
        {
            return (sign == 1 ? 1 : -1);
        }
        else
        {
            int i = 0;
            int len = alen;
            for (i = len - 1; i >= 0; i--)
            {
                if (a->data[i] > b->data[i])
                {
                    return (sign == 1? -1:1);
                }
                else if (a->data[i] < b->data[i])
                {
                    return (sign == 1 ? 1 : -1);
                }
            }
            return 0;
        }
    }
    
    bignumber_s *calc_sub(bignumber_s *a, bignumber_s *b)
    {
        if (a->sign == 0 && b->sign == 0)
        {
            if (cmp(a, b) >= 0)
            {
                int len = a->len;
                bignumber_s *result= make_bignumber_temp(len, 0);
                sub_impl(a, b, result);
                return result;
            }
            else
            {
                int len = b->len;
                bignumber_s *result = make_bignumber_temp(len, 1);
                sub_impl(b, a, result);
                return result;
            }
        }
        else if (a->sign == 1 && b->sign == 1)
        {
            b->sign = 0;
            a->sign = 0;
            return calc_sub(b, a);
        }
        else if (a->sign == 0 && b->sign == 1)
        {
            b->sign = 0;
            bignumber_s *result = calc_add(a, b);
            return result;
        }
        else if (a->sign == 1 && b->sign == 0)
        {
            a->sign = 0;
            bignumber_s *result = calc_add(a, b);
            result->sign = 1;
            return result;
        }
    }
    
    void mul_impl(bignumber_s *x, bignumber_s *y, bignumber_s *z)
    {
        int n = x->len;
        int m = y->len;
        int i = 0;
        int j = 0;
        int carry = 0;
    
        for (; i < m; i++)
        {
            for (j = 0; j < n; j++)
            {
                carry += y->data[i] * x->data[j] + z->data[i+j];
                z->data[i+j] = carry % BASE;
                carry /= BASE;
            }
    
            for (; j + i < m + n; j++)
            {
                carry += z->data[i+j];
                z->data[i+j] = carry % BASE;
                carry /= BASE;
            }
        }
    }
    
    bignumber_s *calc_mul(bignumber_s *a, bignumber_s *b)
    {
        bignumber_s *zero = make_bignumber_temp(1,0);
        if (cmp(a, zero) == 0 || cmp(b, zero) == 0)
        {
            return zero;
        }
        int len = a->len + b->len;
        bignumber_s *result = make_bignumber_temp(len, a->sign == b->sign ? 0 : 1);
        mul_impl(a, b, result);
        return result;
    }
    
    void plusone(bignumber_s *a)
    {
        int len = a->len;
        int i;
        int carry = 1;
        for (i = 0; i < len; i++)
        {
            carry += a->data[i];
            a->data[i] = carry % BASE;
            carry /= BASE;
        }
    }
    
    bignumber_s *calc_div(bignumber_s *a, bignumber_s *b)
    {
        bignumber_s *zero = make_bignumber_temp(1, 0);
        if (cmp(b, zero) == 0)
        {
            fprintf(stderr, "Interfer division by zero
    ");
            exit(-1);
        }
        else if (cmp(a, zero) == 0)
        {
            return zero;
        }
    
        int len = a->len;
        bignumber_s *result = make_bignumber_temp(len, a->sign == b->sign ? 0 : 1);
        a->sign = 0;
        b->sign = 0;
        bignumber_s *temp = make_bignumber_temp(len, 0);
        bignumber_s *aa = a;
        while (1)
        {
            if (cmp(aa, b) >= 0)
            {
                sub_impl(aa, b, temp);
                plusone(result);
                aa = temp;
            }
            else
            {
                free(temp);
                return result;
            }
        }   
    }
    
    int main(int argc, char *argv[])
    {
        char str1[1024] = {0};
        char operator[3] = {0};
        char str2[1024] = {0};
        //scanf("%s %s %s", str1, operator, str2);
        scanf("%s", str1);
        scanf("%s", operator);
        scanf("%s", str2);
        bignumber_s *a = make_bignumber_fromstr(str1);
        bignumber_s *b = make_bignumber_fromstr(str2);
    
        if (0 == strcmp(operator, "+"))
        {
            print_bignumber(calc_add(a, b));
        }
        else if (0 == strcmp(operator, "-"))
        {
            print_bignumber(calc_sub(a, b));
        }
        else if (0 == strcmp(operator, "x"))
        {
            print_bignumber(calc_mul(a, b));
        }
        else if (0 == strcmp(operator, "/"))
        {
            print_bignumber(calc_div(a, b));
        }
        else
        {
            usage(argv[0]);
        }
        return 0;
    }

    在求商的运算中,如果商的值太大,就会出现运算时间很长的情况。

  • 相关阅读:
    Leetcode-645 Set Mismatch
    2017百度软研(C++)
    二叉树中任意两个节点的最近公共祖先
    不用加减乘除做加法
    一些leetcode算法题
    Leetcode 98. Validate Binary Search Tree
    C++ 通过ostringstream 实现任意类型转string
    Leetcode 215. Kth Largest Element in an Array
    382. Linked List Random Node
    一些基础函数的实现
  • 原文地址:https://www.cnblogs.com/wanghao-boke/p/12133132.html
Copyright © 2011-2022 走看看