大数减法(A - B Problem Plus)问题
解题思路
flagA为0表示A为正整数,为-1表示A为负整数;
flagB为0表示B为正整数,为2表示B为负整数;
而 flag = flagA + flagB。
当 flag == 0 表示数A为正整数,数B为正整数
则A - B 可能是正整数或负整数。
当 flag == 1 表示数A为负整数,数B为负整数
则A - B 可能是正整数或负整数。
因为差值可能是正整数,也可能是负整数,所以采用如下方法:
(1) 先判断被减数和减数哪⼀个位数⻓。若被减数位数⻓是正常的减法;若减数位数⻓,则⽤被减数减去减数,最后还要加上负号。
(2) 当两数位数⻓度相等时,最好⽐较哪⼀个数⼤,否则负号处理会很繁琐。处理每⼀项时,如果前⼀位相减有借位,就先减去上⼀位的借位,⽆则不减,再去判断是否能够减开被减数,如果减不开,就要借位后再去减,同时置借位为1,否则置借位为0。
当 flag == -1 表示数A为负整数,数B为正整数
则A - B 一定为负整数。
由于计算时数字去掉了负号,可以则先相加,最后加上负号。
如-3 - 18,是3 + 18 = 21,再加上负号,即-21。
当 flag == 2 表示数A为正整数,数B为负整数
则A - B 一定为正整数。
由于计算时数字去掉了负号,则可以直接相加。
如3 - (-18),是3 + 18 = 21。
样例
输入1:
-3 98
输出1:
-3 - 98 = -101
输入2:
-3 -98
输出2:
-3 - (-98) = 95
输入3:
3 98
输出3:
3 - 98 = -95
代码实现
#include<stdio.h>
#include<string.h>
#define NUM_MAX 1000                // 大数的最大位数
/*
 大数减法
 参数:
 numA为第一个大数
 numB为第二个大数
 difference保存相减的结果  即:numA - numB = difference
 lenA为char指针的长度
 lenB为char指针的长度
 flag为-1表示A为负整数、B为正整数,为0表示A与B均为正整数,
 为1表示A与B均为负整数,为2表示A为正整数、B为负整数
 返回值:返回数组difference的有效长度,即计算结果的位数
 */
void Minus(char* numA, char* numB, int* difference, int lenA, int lenB, int flag)
{
    char* temp = NULL;
    int symbol = 0;                             // symbol为0表示计算结果是正整数,为1表示结果是负整数
    int tempFlag = 0;                           // 临时标志
    int maxLen = lenA > lenB ? lenA : lenB;     // 取字符串numA与numB的最大长度
    // flag == 0 表示数A为正整数,数B为正整数,则A - B 可能是正整数或负整数
    // flag == 1 表示数A为负整数,数B为负整数,则A - B 可能是正整数或负整数
    if (flag == 0 || flag == 1)
    {
        // 如果被减数位数小于减数
        if (lenA < lenB)
        {
            tempFlag = 1;
            // 交换两数,方便计算
            temp = numA;
            numA = numB;
            numB = temp;
            maxLen = lenA;
            lenA = lenB;
            lenB = maxLen;
        }
        else if (lenA == lenB)                  // 如果被减数位数等于减数的位数
        {
            for (int i = 0; i < lenA; i++)
            {
                if (numA[i] == numB[i])
                {
                    continue;
                }
                else if (numA[i] > numB[i])
                {
                    tempFlag = 0;
                    break;
                }
                else
                {
                    tempFlag = 1;
                    temp = numA;
                    numA = numB;
                    numB = temp;
                    break;
                }
            }
        }
    }
    // 数A与B均为正整数
    if (flag == 0)
    {
        if (tempFlag == 0)
        {
            symbol = 0;
        }
        else
        {
            symbol = 1;
        }
    }
    else if (flag == 1)                         // 数A与B均为负整数
    {
        if (tempFlag == 0)
        {
            symbol = 1;
        }
        else
        {
            symbol = 0;
        }
    }
    else if (flag == -1)                        // 数A为负整数,数B为正整数,则A - B 一定为负整数
    {
        symbol = 1;
    }
    else                                        // flag == 2表示数A为正整数,数B为负整数,则A - B 一定为正整数
    {
        symbol = 0;
    }
    int l = 0;
    int k = 0;
    int array[NUM_MAX] = {0};
    // 将numA字符数组的字符数字转换为整型数字,且逆向保存到整型数组sum中,即低位在前,高位在后
    for (int i = lenA - 1; i >= 0; i--)
    {
        difference[k++] = numA[i] - '0';               // 可以使用'9' - '0' = 9的方式将字符数字转换为整型数字
    }
    // 转换第二个数
    for (int j = lenB - 1; j >= 0; j--)
    {
        array[l++] = numB[j] - '0';
    }
    // 两数相减
    // flag == 0 表示数A为正整数,数B为正整数,则A - B 可能是正整数或负整数
    // flag == 1 表示数A为负整数,数B为负整数,则A - B 可能是正整数或负整数
    // 这种情况采用上面的方法:先比较数A与数B的长度,长度相等的话,从第一个元素开始逐位比较值的大小
    // 最终,会用较大的数减去较小的数
    // flag == -1 表示数A为负整数,数B为正整数,则A - B 一定为负整数
    // 由于这里数字去掉了负号,则先计算A + B之和,最后输出的时候再加上负号
    // 如-3 - 8,在这里是3 + 8 = 11,再加上负号,即-11
    // flag == 2 表示数A为正整数,数B为负整数,则A - B 一定为正整数
    // 由于这里数字去掉了负号,则计算A + B之和
    // 如3 - (-8),在这里是3 + 8 = 11,不用加负号
    for (int i = 0; i <= maxLen; i++)
    {
        if (flag == 0 || flag == 1)
        {
            difference[i] -= array[i];             // 两个数从低位开始相减
            if (difference[i] < 0)                 // 判断是否有借位
            {
                difference[i] += 10;
                difference[i+1]--;
            }
        }
        else if (flag == -1 || flag == 2)
        {
            difference[i] += array[i];             // 两个数从低位开始相加
            if (difference[i] > 9)                 // 判断是否有进位
            {
                difference[i] %= 10;
                difference[i+1]++;
            }
        }
    }
    // 计算结果为负数
    if (symbol == 1)
    {
        // 高位maxLen - 1没有值
        if(difference[maxLen] == 0)
        {
            // 在⾼位添加⼀个 -1 表示负数
            difference[maxLen] = -1;
            maxLen++;
        }
        else                                // 高位maxLen - 1有值
        {
            // 在⾼位添加⼀个 -1 表示负数
            difference[maxLen + 1] = -1;
            maxLen = maxLen + 1 + 1;
        }
    }
    else                                    // 计算结果为正数
    {
        if(difference[maxLen] == 0)
        {
            maxLen++;
        }
        else
        {
            maxLen = maxLen + 1 + 1;
        }
    }
    int i = 0;
    // 根据高位是否是-1判断是否是负数
    if (difference[i = maxLen - 1] < 0)
    {
        printf("-");                        // 输出负号
        i--;
    }
    else
    {
        i = maxLen;
    }
    // 高位是0的话不输出,从第一个不是0的位开始输出
    while (difference[i] == 0)
    {
        i--;
    }
    // 打印计算结果
    for ( ; i >= 0; i--)
    {
        printf("%d", difference[i]);
    }
}
int main()
{
    char strA[NUM_MAX] = {0};
    char strB[NUM_MAX] = {0};
    while (scanf("%s%s", strA, strB) != EOF)
    {
        char numA[NUM_MAX] = {0};
        char numB[NUM_MAX] = {0};
        int difference[NUM_MAX] = {0};      // 存放计算的结果,低位在前,高位在后,即sum[0]是低位
        int flag = 0;
        int flagA = 0;                      // flagA为0表示A为正整数,为-1表示A为负整数
        int flagB = 0;                      // flagB为0表示B为正整数,为2表示B为负整数
        int lenA = strlen(strA);            // 计算数组numA的长度,即数A的位数
        int lenB = strlen(strB);            // 计算数组numB的长度,即数B的位数
        // 若为负数,去掉负号,且数字所在字符长度减1
        if (strA[0] == '-')
        {
            flagA = -1;
            lenA--;
        }
        if (strB[0] == '-')
        {
            flagB = 2;
            lenB--;
        }
        // flag为-1表示A为负整数、B为正整数,为0表示A与B均为正整数,
        // 为1表示A与B均为负整数,为2表示A为正整数、B为负整数
        flag = flagA + flagB;
        // 将strA与strB字符串重新存储到numA与numB字符串中,主要为了重新存储去掉负号的字符串
        for (int i = lenA - 1; i >= 0; i--)
        {
            if (flagA == -1)
            {
                numA[i] = strA[i+1];
            }
            else
            {
                numA[i] = strA[i];
            }
        }
        for (int j = lenB - 1; j >= 0; j--)
        {
            if (flagB == 2)
            {
                numB[j] = strB[j+1];
            }
            else
            {
                numB[j] = strB[j];
            }
        }
        if (flagB == 2)
        {
            printf("%s - (%s) = ", strA, strB);
        }
        else
        {
            printf("%s - %s = ", strA, strB);
        }
        // 调用大数减法函数
        Minus(numA, numB, difference, lenA, lenB, flag);
        // 换行
        printf("\n");
    }
    return 0;
}
个人主页:
大数减法(A - B Problem Plus)问题的更多相关文章
- A-B 练习【大数减法举例】
		A-B Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^ 题目描述 题目链接:http://acm.sdut.edu.cn/sdutoj/ ... 
- 2016中国大学生程序设计竞赛(长春)   Ugly Problem   模拟+大数减法
		传送门:http://acm.hdu.edu.cn/showproblem.php?pid=5920 我们的思路是: 对于一个串s,先根据s串前一半复制到后一半构成一个回文串, 如果这个回文串比s小, ... 
- (母函数 Catalan数 大数乘法 大数除法)  Train Problem II   hdu1023
		Train Problem II Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ... 
- 第三周PTA笔记 回文数+A-B(大数减法)+高精度除法+数楼梯(大数加法)
		回文数 对于一个自然数n,若将n的各位数字反向排列所得的数n1与n相等,则称n为回文数,例如2332. 若给定一个N( 2<=N<=16)进制数M(M的长度在一百位以内),如果M不是回文数 ... 
- 大数乘法(A * B Problem Plus)问题
		大数乘法问题一般可以通过将大数转换为数组来解决. 解题思路 第1步 第2步 第3步 第4步 样例输入1 56 744 样例输出1 800 样例输入2 -10 678 样例输出2 -6780 样例输入3 ... 
- 大数加法(A + B Problem Plus)问题
		解题思路 两个⼤数可以⽤数组来逐位保存,然后在数组中逐位进⾏相加,再判断该位相加后是否需要进位.为了⽅便计算,可以把数字的低位放到数组的前面,高位放在后面. 样例输入 3 18 22 56 744 5 ... 
- POJ 2756 Autumn is a Genius 采用string大数减法
		标题意味着小神童.加减可以计算. 只是说这个小神童的学科知识,究竟有多神,自己给自己找. 最后,因为数据是非常非常巨大的,我听说关闭50k结束了50000数字总和,可以想见他神教. 这似乎也是考试题目 ... 
- 杭电ACM(1002) -- A + B Problem II 大数相加 -提交通过
		杭电ACM(1002)大数相加 A + B Problem II Problem DescriptionI have a very simple problem for you. Given two ... 
- hdu-5920 Ugly Problem(贪心+高精度)
		题目链接: Ugly Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Other ... 
随机推荐
- MYSQL常见安装错误集:[ERROR] --initialize specified but the data directory has files in it. Abort
			1.[ERROR] --initialize specified but the data directory has files in it. Abort [错误] -初始化指定,但数据目录中有文件 ... 
- 测开之路一百四十三:ORM框架之SQLAlchemy模型及表创建
			基于前一篇内容,可以使用模型的结构 目录结构 main,入口层 from flask import Flaskfrom flask_sqlalchemy import SQLAlchemy app = ... 
- Android下Native的so编译:使用cmakelists.txt
			android studio的CMakeLists.txt写好后,在Studio中编译没问题,在命令编译时则需要配置很多参数才能成功 示例CMakeLists.txt文件: cmake_minimum ... 
- Java 语言特性之 Annotation 注解
			利用 Java 的反射机制,可以在运行时获取 Java 类的注解信息. 注解 注解的特性 注解是 Java 5 的一个新特性,是插入代码中的一种注释或者说是元数据.注解并不是程序代码,可以对程序作出解 ... 
- Shiro  Demo 示例(SpringMVC-Mybatis-Shiro-redis)
			Shiro Demo 准备工作 运行前申明 请看完本页面的所有细节,对你掌握这个项目来说很重要,别一上来就搞,你不爽,我也不爽. 本项目需要一定的Java功底,需要对SpringMvc,Mybatis ... 
- java一周学习记录(2017/12/2)
			姓名:Danny 日期:2017/12/2 周日 周一 周二 周三 周四 周五 周六 所花时间 120 150 190 150 180 28 ... 
- .net core 学习小结之环境配置篇
			安装IIs对 netcore 的支持 https://docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/aspnet-core-mod ... 
- 使用原生js 获取用户访问项目的浏览器类型
			想要获取浏览器的类型很简单,网上提供了很多方法,但是看过之后,都是根据浏览器内核来判断是ie,谷歌,火狐,opeara的, 所以不能进一步判断在国内使用的主流浏览器类型,比如360,百度,搜狐浏览器等 ... 
- MySQL-快速入门(6)连接查询、子查询、正则表达式查询、数据的插入删除更新
			1.内连接查询:inner join ... on 只有满足条件的记录才能够出现在结果关系中,即完全相等.自连接查询是一种特殊的内连接查询. 2.外连接查询: 1>左外连接 / 左连接:返回包括 ... 
- roslyn\csc.exe
			vs2019调试运行时提示roslyn\csc.exe错误时在nuget包管理器控制台里输入: Update-Package Microsoft.CodeDom.Providers.DotNetCo ... 
