(1)读取两个字符串后,根据小数点位置,对齐两个字符串,不足位用0补齐
(2)从低位开始计算加、减、乘,并依次累加存储如结果阵列
(3)去掉结果阵列首尾的0
用测试用例2进行了测试,结果如下:
代码:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#define MAXNUM (int)60
//去除前面的0
void deletePreZero(char c[])
{
int i;
while (c[0] == '0')
{
for (i = 0; i < strlen(c) - 1; i++)
c[i] = c[i + 1];
c[strlen(c) - 1] = 0;
}
}
//去除后面的0
void deleteBackZero(char c[])
{
int i = strlen(c) - 1;
while (c[i] == '0')
{
c[i] = 0;
i = strlen(c) - 1;
}
}
//小数点对齐
void duiqi(char a[], char b[], int* flaga, int* flagb)
{
int lena_int = 0; //a整数部分长度
int lena_float = 0; //a小数部分长度
int lenb_int = 0; //b
int lenb_float = 0;
int i = 0;
int t;
int indexa, indexb;
int lena, lenb;
//正负数
if (a[0] == '-')
{
*flaga = 1;
a[0] = '0';
}
else
*flaga = 0;
if (b[0] == '-')
{
*flagb = 1;
b[0] = '0';
}
else
*flagb = 0;
lena = strlen(a);
lenb = strlen(b);
//计算a的整数部分长度
while (a[i] != '\0' && a[i] != '.')
{
lena_int++;
i++;
}
//计算a的小数部分长度
if (a[i] == '.')
{
i++;
while (a[i] != '\0')
{
lena_float++;
i++;
}
}
//计算b的整数部分长度
i = 0;
while (b[i] != '\0' && b[i] != '.')
{
lenb_int++;
i++;
}
//计算b的小数部分长度
if (b[i] == '.')
{
i++;
while (b[i] != '\0')
{
lenb_float++;
i++;
}
}
//对齐长度
t = lena_float > lenb_float ? lena_float : lenb_float;
t = t + (lena_int > lenb_int ? lena_int : lenb_int);
t += 1; //加一个小数点,得到总长度
a[t] = 0;
b[t] = 0;
if (lena_float > lenb_float) //a的小数部分比b长
{
//a整体右移
indexa = t - 1;
for (i = lena - 1; i >= 0; i--, indexa--)
a[indexa] = a[i];
//前面补0
while (indexa >= 0)
{
a[indexa] = '0';
indexa--;
}
//a的小数部分长,则b的小数部分补0,补0的个数为lena_float - lena_float
indexb = t - 1;
i = 0;
while (i < lena_float - lenb_float)
{
b[indexb] = '0';
indexb--;
i++;
}
//b整体右移
for (i = lenb - 1; i >= 0; i--, indexb--)
b[indexb] = b[i];
//b前面补0
while (indexb >= 0)
{
b[indexb] = '0';
indexb--;
}
}
else //b的小数部分比a长
{
//b整体右移
indexb = t - 1;
for (i = lenb - 1; i >= 0; i--, indexb--)
b[indexb] = b[i];
//b前面补0
while (indexb >= 0)
{
b[indexb] = '0';
indexb--;
}
//a小数后面补0
i = 0;
indexa = t - 1;
while (i < lenb_float - lena_float)
{
a[indexa] = '0';
indexa--;
i++;
}
//a整体右移
for (i = lena - 1; i >= 0; i--, indexa--)
a[indexa] = a[i];
//a前面补0
while (indexa >= 0)
{
a[indexa] = '0';
indexa--;
}
}
//输出对齐后的数
/*printf("对齐后的数:\n");
if (*flaga == 1)
printf("-%s\n", a);
else
printf("+%s\n", a);
if(*flagb == 1)
printf("-%s\n", b);
else
printf("+%s\n", b);*/
}
//比较大小
int isbig(char a[], char b[])
{
return strcmp(a, b);
}
//大数相加,在运算前,先将数字对齐
void bigAdd(char a[], char b[], char c[])
{
int maxlen = strlen(a) + 1; //a和b等长度,结果的最大值是 strlen(a)+1
int i, j, shift = 0, t = 0;
for (i = 0; i < maxlen; i++)
c[i] = '0'; //填充'0'
c[maxlen] = 0;//结尾标记
i = strlen(a) - 1;
j = maxlen - 1;
//计算小数部分
while (a[i] != '.')
{
t = (a[i] - '0') + (b[i] - '0') + shift;
if (t >= 10)
{
t -= 10;
shift = 1;
c[j] = '0' + t;
}
else
{
shift = 0;
c[j] = '0' + t;
}
i--;
j--;
}
c[j] = '.';
i--;
j--;
while (i >= 0)
{
t = (a[i] - '0') + (b[i] - '0') + shift;
if (t >= 10)
{
t -= 10;
shift = 1;
c[j] = '0' + t;
}
else
{
shift = 0;
c[j] = '0' + t;
}
i--;
j--;
}
if (shift)
c[j] = '0' + shift;
//删除前后的0
deletePreZero(c);
deleteBackZero(c);
}
//大数相减,在运算前,先将数字对齐,并用大数减去小数
void bigSub(char a[], char b[], char c[])
{
int maxlen = strlen(a); //减法结果的长度不会超过元字符长度
int i, j, t, shift = 0;
for (i = 0; i < maxlen; i++)
c[i] = '0'; //填充'0'
c[maxlen] = 0; //结尾标记
i = strlen(a) - 1;
j = maxlen - 1;
//计算小数部分
while (a[i] != '.')
{
t = a[i] - b[i] - shift; //是否有借位
if (t < 0)
{
t += 10;
shift = 1;//有借位
c[j] = '0' + t;
}
else
{
shift = 0;//无借位
c[j] = '0' + t;
}
i--;
j--;
}
c[j] = '.';
i--;
j--;
//计算整数部分
while (i >= 0)
{
t = a[i] - b[i] - shift; //是否有借位
if (t < 0)
{
t += 10;
shift = 1;//有借位
c[j] = '0' + t;
}
else
{
shift = 0;//无借位
c[j] = '0' + t;
}
i--;
j--;
}
//删除前后的0
deletePreZero(c);
deleteBackZero(c);
}
//大数相乘
void bigMul(char a[], char b[], char c[])
{
int lena = strlen(a);
int lenb = strlen(b);
int maxlen = lena + lenb + 1;
int i, j, t, k, shift = 0;
int indextmp;
char tmp[MAXNUM * 2 + 1] = { 0 }; //存储临时结果
//得到a和b的小数位数
int lena_float = 0, lenb_float = 0;
int ff = 0;
i = 0;
while (a[i] != '\0')
{
if (a[i] == '.')
ff = 1;
if (ff == 1 && a[i] >= '0' && a[i] <= '9')
lena_float++;
i++;
}
i = 0;
ff = 0;
while (b[i] != '\0')
{
if (b[i] == '.')
ff = 1;
if (ff == 1 && b[i] >= '0' && b[i] <= '9')
lenb_float++;
i++;
}
//初始化c
for (i = 0; i < MAXNUM * 2; i++)
c[i] = '0';
c[MAXNUM * 2] = 0; //结尾
for (i = lenb - 1, j = 0; i >= 0; i--)
{
if (b[i] == '.')
continue;
//重置tmp
for (k = 0; k < MAXNUM * 2; k++)
tmp[k] = '0';
//tmp的偏移位
indextmp = MAXNUM * 2 - j - 1;
//用b的每一位去乘a,并存储到tmp中
for (k = lena - 1; k >= 0; k--)
{
if (a[k] == '.')
continue;
t = (b[i] - '0') * (a[k] - '0') + shift;
if (t >= 10)
{
shift = t / 10;
t = t % 10;
}
else
{
shift = 0;
}
tmp[indextmp] = '0' + t;
indextmp--;
}
if (shift)
{
tmp[indextmp] = '0' + shift;
shift = 0;
}
//tmp与c相加
//printf("tmp=%s\n", tmp);
shift = 0;
for (k = MAXNUM * 2 - 1; k >= 0; k--)
{
t = tmp[k] - '0' + c[k] - '0' + shift;
if (t >= 10)
{
t -= 10;
shift = 1;
}
else
shift = 0;
c[k] = '0' + t;
}
j++;
}
//小数点的位数
//printf("c=%s\n", c);
for (i = 0; i < MAXNUM * 2 - (lena_float + lenb_float); i++)
c[i] = c[i + 1];
c[MAXNUM * 2 - lena_float - lenb_float - 1] = '.';
//printf("c=%s\n", c);
//删除前后的0
deletePreZero(c);
}
int main()
{
char a[MAXNUM + 1], b[MAXNUM + 1], c[MAXNUM * 2 + 1];
int flaga, flagb;
int ret;
//strcpy(a, "54375594968196412353419.7136567768967814548988");
//strcpy(b, "73287424855639561252347.4564956732129084076487");
scanf("%s", a);
scanf("%s", b);
duiqi(a, b, &flaga, &flagb); //对齐处理后,消除了a和b的符号位,a和b中只保留数字部分,flaga和flagb记录a和b的正负性
if (flaga == 0 && flagb == 0) //都是正数
{
bigAdd(a, b, c); //加法
printf("%s\n", c);
//减法,用大数减去小数,并根据符号决定是否取反
ret = isbig(a, b);
if (ret == 1)
{
bigSub(a, b, c);
printf("%s\n", c);
}
else if (ret == 0)
printf("0\n");
else
{
bigSub(b, a, c);
printf("-%s\n", c);
}
//乘法
deleteBackZero(a);
deletePreZero(a);
deleteBackZero(b);
deleteBackZero(b);
bigMul(a, b, c);
printf("%s\n", c);
}
else if (flaga == 0 && flagb == 1) //a是正数,b是负数
{
//加法,因有负数,实际调用减法求加法的结果
ret = isbig(a, b);
if (ret == 1)
{
bigSub(a, b, c);
printf("%s\n", c);
}
else if (ret == 0)
printf("0\n");
else
{
bigSub(b, a, c);
printf("-%s\n", c);
}
//减法,实际是加法
bigAdd(a, b, c);
printf("%s\n", c);
//乘法
deleteBackZero(a);
deletePreZero(a);
deleteBackZero(b);
deleteBackZero(b);
bigMul(a, b, c);
printf("-%s\n", c);
}
else if (flaga == 1 && flagb == 0) //a是负数,b是正数
{
//加法,实际是减法
ret = isbig(b, a);
if (ret == 1)
{
bigSub(b, a, c);
printf("%s\n", c);
}
else if (ret == 0)
printf("0\n");
else
{
bigSub(a, b, c);
printf("-%s\n", c);
}
//减法,实际是加法,结果取反
bigAdd(a, b, c);
printf("-%s\n", c);
//乘法
deleteBackZero(a);
deletePreZero(a);
deleteBackZero(b);
deleteBackZero(b);
bigMul(a, b, c);
printf("-%s\n", c);
}
else //都是负数
{
//加法,结果取反
bigAdd(a, b, c);
printf("-%s\n", c);
//减法,实际是b-a
ret = isbig(b, a);
if (ret == 1)
{
bigSub(b, a, c);
printf("%s\n", c);
}
else if (ret == 0)
printf("0\n");
else
{
bigSub(a, b, c);
printf("-%s\n", c);
}
//乘法
deleteBackZero(a);
deletePreZero(a);
deleteBackZero(b);
deleteBackZero(b);
bigMul(a, b, c);
printf("%s\n", c);
}
return 0;
}