大数相除,保留小数后18位。
例如:6666666666666/555555555555555=0.011999999999998812
输入:如例子所示的两个“大数”,用空格隔开。数字范围在 10~20 位之间。 输出:计算结果(小数点后面保留 18 位)
代码:
//利用大数减法,为了减少运算量,控制除数一直比被除数小一位;
#include<iostream>
#include<cstring>
using namespace std;
char b[22];
int k = 0;//记录小数点后的位数
int p = 0;
int sff[20][20];//记录每次相除的结果,及对应每次相差的位数
int len3;//除数的长
void divide(char a[22], char m[22], int, int, int);//将被control函数控制了位数的除数与被除数进行除法运算,并将得到的余数作为被除数,返回到control函数中
void control(char a[22], char b[22], int, int);//控制除数一直比被除数小一位
void divide(char a[22], char m[22], int c, int len1, int len2)
{
char str1[22],str2[22];
int i, j, yes;
int l = 0;
for (i = len1 - 1, j = 0; i >= 0; i--, j++)//将除数和被除数复制下来
str1[j] = a[i];
str1[j] = '\0';
for (i = len2 - 1, j = 0; i >= 0; i--, j++)
str2[j] = m[i];
str2[j] = '\0';
while (1)
{
l++;//每减一次加一,最后为每一次相除的结果
yes = 0;
for (i = 0; i < len2; i++)//相减
{
str1[i] = str1[i] - str2[i] + 48;
if (str1[i] < 48)
{
str1[i] = 58 - (48-str1[i]);
str1[i + 1]--;
}
}
for (i = len1 - 1; i >= 0; i--)
{
if (str1[i] != '0')
{
str1[i + 1] = '\0';
break;
}
}len1 = i + 1;//重新确认一下被除数的大小
if (len1 <= len2)//判断一下被除数是否还够减,若不够跳出循环
{
if (len1 == len2)
{
for (i = len1-1; i >= 0; i--)
{
if (str1[i] != str2[i])
{
if (str1[i] < str2[i])
{
yes = 1;
}
else
{
yes = 0;
}
break;
}
}
if (yes)
{
break;
}
}
else
{
break;
}
}
}
sff[p][0] = l;//记录一下每一次相除的结果
sff[p][1] = c;//记录一下每一次相除的余数,与除数相差的位数
p++;
if (!len1)//如果提前整除了,结束
{
return;
}
if (c <= 0)
{
k = k + c - 1;
}
if (k <-18)//如果结果超过了小数点后18位,结束
return;
for (i = len1 - 1, j = 0; i >= 0; i--, j++)
{
a[i] = str1[j];
}
a[j] = '\0';
control(a, b, len1, len3);
}
void control(char a[22], char b[22], int len1, int len2)
{
int i;
int c;//记录每次除数与被除数的位数差值
char m[22];
for (i = 0; i < len2; i++)
{
m[i] = b[i];
}//将除数复制一下
m[len2] = '\0';
if (len1 >= len2)//补零,控制除数比被除数小一位
{
c = len1 - len2;
if (c == 0)
{
a[len1] = '0';
len1++;
a[len1] = '\0';
}
else
{
for (i = 0; i < c - 1; i++)
{
m[len2] = '0';
len2++;
}
m[len2] = '\0';
}
}
else
{
c = len1 - len2;
for (i = 0; i < -c + 1; i++)
{
a[len1] = '0';
len1++;
a[len1] = '\0';
}
}
divide(a, m, c, len1, len2);
}
int main()
{
char a[22];
int len1, m = 0, i,j,opp=0,r=0,yes=0,op,mm=0;
int result[40] = { 0 };//储存结果
cin >> a;
cin >> b;
len1 = strlen(a);
len3 = strlen(b);
op = len1 - len3;
control(a, b, len1, len3);
for (i = 0; i < p; i++)//储存结果
{
if (sff[i][1] > 0)//如果在还没控制位数的时候,被除数的位数比除数的位数大的情况
{
k = 10000;
if (sff[i][0] > 9)
{
for (j = 0; j < (sff[i - 1][1] - sff[i][1] - 2); j++)
{
result[m] = 0;
m++;
}
if ((sff[i - 1][1] - sff[i][1] - 1) > 0)
{
mm = mm + sff[i - 1][1] - sff[i][1] - 1;
}
result[m] = sff[i][0] / 10;
m++;
result[m] = sff[i][0] % 10;
}
else
{
for (j = 0; j < (sff[i - 1][1] - sff[i][1]-1); j++)
{
result[m] = 0;
m++;
}
if ((sff[i - 1][1] - sff[i][1] - 1) > 0)
{
mm = mm + sff[i - 1][1] - sff[i][1] - 1;
}
result[m] = sff[i][0];
}
}
else//等于或小于的情况
{
opp++;//
if (sff[i][0] > 9)
{
if (opp == 1)//记录小数点的位置
{
for (j = 0; j < (sff[i - 1][1] - sff[i][1] - 2); j++)
{
result[m] = 0;
m++;
}
if (sff[i][1] == 0)
{
k = m + 1;
}
else
{
k = m;
}
}
for (j = 0; j < -sff[i][1]-1; j++)
{
result[m] = 0;
m++;
}
result[m] = sff[i][0] / 10;
m++;
result[m] = sff[i][0] % 10;
}
else
{
if (opp == 1)//记录小数点的位置
{
if (sff[i][1] >= 0)
{
for (j = 0; j < (sff[i - 1][1] - sff[i][1] - 1); j++)
{
result[m] = 0;
m++;
}
k = m;
}
else
{
for (j = 0; j < (sff[i - 1][1] - sff[i][1] - 2); j++)
{
result[m] = 0;
m++;
}
k = m;
}
}
for (j = 0; j < -sff[i][1]; j++)
{
result[m] = 0;
m++;
}
result[m] = sff[i][0];
}
}
m++;
}
for (i = 0; i < m; i++)
{
if (i == k)
{
if (i == 0)
{
cout << "0.";
}
else
cout << ".";
yes = 1;
}
if (yes)//控制到小数点后18位
r++;
cout << result[i] ;
if (r == 18)
break;
}
if (r < 18)//控制到小数点后18位,提前整除的情况
{
if (r == 0)
{
k = op - p-mm;
}
for (i = r; i < 18; i++)
{
if (i == k&&r==0)
cout << ".";//特殊情况
cout << "0";
}
}
return 0;
}