C语言实现 大数运算 加减乘除模运算 超详细

 加法运算

比较字符串的长度,标记为  max   min;

创建一个 比max字符串长度大1的输出空间,指针result标记其位置;

字符串尾对齐,字符从最小位开始依次相加,大于’10’ 就进位;

若max最高位不进位,返回 result + 1; 否则最前位赋 ’1’, 直接返回result;

C语言实现 大数运算 加减乘除模运算 超详细_第1张图片

C语言实现 大数运算 加减乘除模运算 超详细_第2张图片

// maxer函数 判断str1 是否 大于str2
int maxer(char *str1, char *str2)
{
    int len1 = strlen(str1);
    int len2 = strlen(str2);
    if (len1 > len2)
        return 1;
    else if (len1 < len2)
        return -1;
    else
    {
        int n = strcmp(str1, str2);
        if (n > 0)
            return 1;
        else if (n == 0)
            return 0;
        else
            return -1;
    }
}

//  加法运算
char *add(char *str1, char *str2)
{
    //  确定较大,较小的字符串,并获取它们的长度
    int n = maxer(str1, str2);
    char *max_str = n >= 0 ? str1 : str2;
    char *min_str = n >= 0 ? str2 : str1;
    int len_max = strlen(max_str);
    int len_min = strlen(min_str);

    //  创建 较大字符串 长度大1 的空间 存储结果
    char *str = malloc(MAX_SIZE + 1);
    str[len_max + 1] = '\0';

    //  进行加法运算
    int plus = 0;        // plus 为 进位
    int i = len_max - 1; // 标记 较大字符串 最低位字符的位置
    int j = len_min - 1; // 标记 较小字符串 最低位字符的位置
    for (; i >= 0; i--)
    {
        if (j >= 0)
        {
            str[i + 1] = max_str[i] + min_str[j] - '0' + plus; // 字符相加
            j--;                                               // 位置左移 1
            plus = str[i + 1] > '9' ? 1 : 0;                   // 判断是否进位
            if (plus == 1)
                str[i + 1] -= 10; // 进位 则减 10
        }
        else // 较小字符串的字符 全部加完
        {
            str[i + 1] = max_str[i] + plus;
            plus = str[i + 1] > '9' ? 1 : 0;
            if (plus == 1)
                str[i + 1] -= 10;
        }
    }

    //  根据 最高位 是否 进位,确定 返回指针
    if (plus == 0)
        return str + 1; // 返回 str 右移1位的位置
    else
    {
        str[0] = '1'; // str首位 赋 '1'
        return str;   // 返回 str
    }
}

 减法运算

与加法类似;

比较字符串的大小,先确定结果正负,标记 max min;

创建一个 比max字符串长度大1的输出空间,指针result标记其位置;

字符串尾对齐,字符从最小位开始依次相减,小于’0’ 就进退位; 通过 最后一个前位’0’的位置 和 结果正负 确定返回的位置;

若正:返回最后一个前置’0’后移1位的地址; 若负:将最后一个前置’0’ 改为 ‘-’,并返回其地址

C语言实现 大数运算 加减乘除模运算 超详细_第3张图片

C语言实现 大数运算 加减乘除模运算 超详细_第4张图片

//  确定结果 正负 或 0
    int is_neg = maxer(str1, str2);
    if (is_neg == 0)
        return "0"; // 若为 0, 直接返回 "0" 结束

    char *max_str = is_neg > 0 ? str1 : str2;
    char *min_str = is_neg > 0 ? str2 : str1;
    int len_max = strlen(max_str);
    int len_min = strlen(min_str);

    char *str = malloc(MAX_SIZE + 1);
    str[len_max + 1] = '\0';

    //  进行减法运算
    int plus = 0; // plus 为退位
    int i = len_max - 1;
    int j = len_min - 1;
    for (; i >= 0; i--)
    {
        if (j >= 0)
        {
            str[i + 1] = max_str[i] - min_str[j] + '0' + plus; // 字符相减
            j--;
            plus = str[i + 1] < '0' ? -1 : 0; // 是否 退位
            if (plus == -1)
                str[i + 1] += 10; // 退位 则加 10
        }
        else
        {
            str[i + 1] = max_str[i] + plus;
            plus = str[i + 1] < '0' ? -1 : 0;
            if (plus == -1)
                str[i + 1] += 10;
        }
    }

    //  确定最后一个 前位0 的位置,默认 str首位 为'0'
    int n_zero = 0;
    for (int i = 1; i <= len_max; i++)
    {
        if (str[i] != '0')
            break;
        n_zero++;
    }

    //  根据 正负 和 最后一个前位0的位置 确定 返回指针
    if (is_neg < 0)
    {
        str[n_zero] = '-';   // 将最后一个前置0的 赋为 '-'
        return str + n_zero; // 返回'-'的位置
    }
    else
        return str + n_zero + 1; // 返回最后一个前置0 右移1位的位置
}

 乘法运算

比较字符串的长度,标记为  max   min(提高效率);

从左到右,通过min 的字符,确定增加了几次max,然后通过min字符的位数往后补’0’;再把每次结果相加;

C语言实现 大数运算 加减乘除模运算 超详细_第5张图片

char *mul(char *str1, char *str2)
{
    // 判断 str1 和 str2 中是否为 0,若有, 返回 "0" 结束
    if (*str1 == '0' || *str2 == '0')
        return "0";

    // 提高效率
    int n = maxer(str1, str2);
    char *max_str = n > 0 ? str1 : str2;
    char *min_str = n > 0 ? str2 : str1;
    int len_min = strlen(min_str);

    // 进行乘法运算
    char *str_sum = "0";
    // str2每个字符 乘 str1
    for (int i = 0; i < len_min; i++)
    {
        char *str = "0";
        int m = (int)(min_str[i] - '0'); // 把字符转成整型
        if (m == 0)
            continue;
        else
        {
            for (int j = 0; j < m; j++)
                str = add(str, max_str);
        }
        // 根据字符位数 往str后面 添 '0'
        int len = strlen(str);
        for (int j = 0; j < len_min - i - 1; j++)
        {
            str[len + j] = '0';
        }
        str[len + len_min - i - 1] = '\0';
        //printf("%s\n", str);
        // 将每次得到的结果相加
        str_sum = add(str_sum, str);
        //printf("%s\n", str_sum);
    }
    return str_sum;
}

 除法及取模运算

判断str1 和 str2 的大小,str1 < str2 直接结束,返回 0(除法),str1(取模);

将str1和 str2 对齐,并记录移动位数 n(补0的个数);

若str1 > = str2 , str1一直自减 str 2,直到 str1 < str2 , 记录次数 m;

result 增加 m * 10 的n次方;

若 str1 < str2, 去除str末尾的’0’(即缩小10倍),并将n自减1,继续上步操作;

若n<0,停止操作;

C语言实现 大数运算 加减乘除模运算 超详细_第6张图片

// 除法计算
char *divi(char *str1, char *str2)
{
    // 解决一些特殊情况
    if (*str2 == '0')
        return " 0 不能作为除数!";
    if (maxer(str1, str2) == -1)
        return "0";

    // 初始化 余数(被除数) 除数 和 结果
    char *str_mol = add(str1, "0");  // 得到 str1 副本
    char *str_divi = add(str2, "0"); // 得到 str2 副本
    char *str_sum = "0";

    // 进行除法运算
    // 将 str_mol 和 str_divi 右对齐
    int n = strlen(str1) - strlen(str2);
    char *str_n = "1";
    for (int i = 0; i < n; i++)
        str_n = mul(str_n, "10");    // 得到str_divi 扩大的倍数
    str_divi = mul(str_divi, str_n); // 实现右对齐

    for (int i = 0; i <= n; i++)
    {
        while (maxer(str_mol, str_divi) >= 0)
        {
            str_mol = sub(str_mol, str_divi);
            str_sum = add(str_sum, str_n); // 将每次结果加起来
            //puts(str_mol);
            //puts(str_sum);
        }
        if (i < n)
        {
            *(str_n + strlen(str_n) - 1) = '\0';       // 去除尾位置的 '0'
            *(str_divi + strlen(str_divi) - 1) = '\0'; // 去除尾位置的 '0'
        }
    }
    return str_sum;
}

// 取模
char *mol(char *str1, char *str2)
{
    if (*str2 == '0')
        return " 0 不能作为除数!";
    if (maxer(str1, str2) == -1)
        return str1;
    char *str_mol = add(str1, "0");
    char *str_divi = add(str2, "0");
    char *str_sum = "0";
    int n = strlen(str1) - strlen(str2);
    char *str_n = "1";
    for (int i = 0; i < n; i++)
        str_n = mul(str_n, "10");
    str_divi = mul(str_divi, str_n);
    for (int i = 0; i <= n; i++)
    {
        while (maxer(str_mol, str_divi) >= 0)
        {
            str_mol = sub(str_mol, str_divi);
            str_sum = add(str_sum, str_n);
        }
        if (i < n)
        {
            *(str_n + strlen(str_n) - 1) = '\0';
            *(str_divi + strlen(str_divi) - 1) = '\0';
        }
    }
    return str_mol;
}

你可能感兴趣的:(c语言)