解题思路

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;
}

个人主页:

www.codeapes.cn

大数减法(A - B Problem Plus)问题的更多相关文章

  1. A-B 练习【大数减法举例】

      A-B Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 题目链接:http://acm.sdut.edu.cn/sdutoj/ ...

  2. 2016中国大学生程序设计竞赛(长春) Ugly Problem 模拟+大数减法

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=5920 我们的思路是: 对于一个串s,先根据s串前一半复制到后一半构成一个回文串, 如果这个回文串比s小, ...

  3. (母函数 Catalan数 大数乘法 大数除法) Train Problem II hdu1023

    Train Problem II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  4. 第三周PTA笔记 回文数+A-B(大数减法)+高精度除法+数楼梯(大数加法)

    回文数 对于一个自然数n,若将n的各位数字反向排列所得的数n1与n相等,则称n为回文数,例如2332. 若给定一个N( 2<=N<=16)进制数M(M的长度在一百位以内),如果M不是回文数 ...

  5. 大数乘法(A * B Problem Plus)问题

    大数乘法问题一般可以通过将大数转换为数组来解决. 解题思路 第1步 第2步 第3步 第4步 样例输入1 56 744 样例输出1 800 样例输入2 -10 678 样例输出2 -6780 样例输入3 ...

  6. 大数加法(A + B Problem Plus)问题

    解题思路 两个⼤数可以⽤数组来逐位保存,然后在数组中逐位进⾏相加,再判断该位相加后是否需要进位.为了⽅便计算,可以把数字的低位放到数组的前面,高位放在后面. 样例输入 3 18 22 56 744 5 ...

  7. POJ 2756 Autumn is a Genius 采用string大数减法

    标题意味着小神童.加减可以计算. 只是说这个小神童的学科知识,究竟有多神,自己给自己找. 最后,因为数据是非常非常巨大的,我听说关闭50k结束了50000数字总和,可以想见他神教. 这似乎也是考试题目 ...

  8. 杭电ACM(1002) -- A + B Problem II 大数相加 -提交通过

    杭电ACM(1002)大数相加 A + B Problem II Problem DescriptionI have a very simple problem for you. Given two ...

  9. hdu-5920 Ugly Problem(贪心+高精度)

    题目链接: Ugly Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Other ...

随机推荐

  1. nohup后台运行

    1.信息输出 nohup java -jar xxxx.jar & 2.信息不输出 nohup java -jar xxxx.jar >/dev/null 2>&1 &am ...

  2. http协议组成

    摘要 本文主要内容介绍什么是http协议 了解http协议之前我们先了解一下当我们输入一个url到页面渲染出来,这个过程发什么了什么呢~ 网络开启线程开始解析url DNS解析域名,查询IP 建立TC ...

  3. C#得到10000以内素数

    偶数除了二都不是素数 一个数 n 如果是合数,那么它的所有的因子不超过sqrt(n)--n的开方 int i, j, n = 10000; for (i = 3; i <= n; i += 2) ...

  4. office问题解决办法汇总

    1.Office2007或2010提示:您正试图运行的函数包含有宏或需要宏语言支持的内容 解决办法:word选项--加载项--管理com加载项--转到--把所有加载项删除 2.excel2010打开三 ...

  5. ipad已停用 连接itunes怎么办

    问题描述: ipad 开机密码多次输入出错后,提示 ipad已停用 连接itunes 解决方法: 参考: https://jingyan.baidu.com/article/fb48e8bee9ef4 ...

  6. IDEA神器

    破解 路径:添加-javaagent:JetbrainsCrack-2.7-release-str.jar的路径 例-javaagent:D:\Program Files\JetBrains\Inte ...

  7. exists、in和join比较

    这个根据实际情况具体分析 遇到问题了再具体分析就行.

  8. [MicroSoft]Introducing .NET 5

    Introducing .NET 5 Richard https://devblogs.microsoft.com/dotnet/introducing-net-5/ 将路线图 完整的给出来了. Ma ...

  9. Javascript原型介绍

    原型及原型链 原型基础概念 function Person () { this.name = 'John'; } var person = new Person(); Person.prototype ...

  10. tensorflow学习笔记七----------卷积神经网络

    卷积神经网络比神经网络稍微复杂一些,因为其多了一个卷积层(convolutional layer)和池化层(pooling layer). 使用mnist数据集,n个数据,每个数据的像素为28*28* ...