Damn! 高精度!

P1601 A+B Problem(高精) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

“用原始的方法模拟计算,有品。”


 当语言的基本数学数据类型存放不了一个数字,就应该考虑高精度了。

目录

P1601 A+B Problem(高精) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

高精度加法

全部代码

P1303 A*B Problem - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

高精度乘法

全部代码

高精度a的b次方 

全部代码


高精度加法

 

512
+548
=1060

想要实现加法,我们需要三个东西,加数,被加数,进位数。加数加被加数加上进位数mod10就是该位的答案。例如上面的第一位和第二位,第一位是(2+8+0)%10得到该位的答案是0,第二位是(1+4+1)%10得到该位的答案是6。故在代码里面我们的实现思路也是如此。

既然基本的数学数据类型存放不了数字,那我们就用先字符串去存放一个数字,然后再拆分成一个数组。高精度加法第一步就是用字符串保存数字,然后转化为数字数组。

	cin >> a;
	cin >> b;
// a和b为字符串string
	for (int i = 0; i < a.length(); i++)
	{
		ra[i] = a[a.length() - i - 1] - '0';
	}
//a如果是"123"
//那么ra里面放的就是321
	for (int i = 0; i < b.length(); i++)
	{
		rb[i] = b[b.length() - i - 1] - '0';
	}
//同时将数字反转
//方便后续的加法模拟
//因为加法是从低位开始加的

高精度加法第二步就是模拟加法。按之前说的加数加上被加数加上进位数mod10。

int len = max(a.length(), b.length());
//for循环的次数
//需要按照大的数字长度来进行加法
//123+12
//就是需要循环加3次
	for (int i = 0; i < len; i++)
	{
		c[i] += ra[i] + rb[i];
//加数加被加数加进位数
		c[i + 1] = c[i] / 10;
//更新下一位的进位数
		c[i] = c[i] % 10;
//mod10得到该位的结果
	}

高精度加法第三步考虑前导零。因为600+600的结果是1200,如果你不考虑前导零,那么最后的输出结果就会是200,而不是1200。

	while (c[len] != 0)
	{
		len++;
	}

全部代码

#include <iostream>
#include <string>
using namespace std;
const int N = 1e3;
string a, b;
int ra[N], rb[N], c[N];

int main()
{
	cin >> a;
	cin >> b;
	for (int i = 0; i < a.length(); i++)
	{
		ra[i] = a[a.length() - i - 1] - '0';
	}
	for (int i = 0; i < b.length(); i++)
	{
		rb[i] = b[b.length() - i - 1] - '0';
	}
	int len = max(a.length(), b.length());
	for (int i = 0; i < len; i++)
	{
		c[i] += ra[i] + rb[i];
		c[i + 1] = c[i] / 10;
		c[i] = c[i] % 10;
	}
	while (c[len] != 0)
	{
		len++;
	}
	for (int i = 0; i < len; i++)
		cout << c[len - i - 1];
	return 0;
}

P1303 A*B Problem - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

“这世上本没有路,走的人多了,也便成了路。”


高精度乘法

123
X12
=>246
=>123
=1476

高精度乘法与加法第一步是一致的。读取字符串并拆分反转成数组。因为都是从低位开始进行运算操作的。

    cin >> a;
	cin >> b;
	for (int i = 0; i < a.length(); i++)
	{
		ra[i] = a[a.length() - i - 1] - '0';
	}
	for (int i = 0; i < b.length(); i++)
	{
		rb[i] = b[b.length() - i - 1] - '0';
	}

高精度乘法第二步就是乘法模拟了。

    int len = a.length() + b.length();
	for (int i = 0; i < a.length(); i++)
		for (int j = 0; j < b.length(); j++)
		{
			c[i + j] += ra[i] * rb[j];
//乘数乘以被乘数 加上进位数
			c[i + j + 1] += c[i + j] / 10;
//更新下一位的进位数
			c[i + j] = c[i + j] % 10;
//取模得到该位的答案
		}
// c[1]在循环中会出现两次
//一次是i=0 j=1
//一次是i=1 j=0
//就好比是
// 123
//  12
//-----
// 246
//123
//-----
//1476
//c[1]出现了两次
//第一次是246中的4
//第二次是123中的3
//两次相加取模进位就是该位的答案7

高精度乘法最后就是去除前导零。一定要注意len>1,因为零乘以任何数都等于零,结果如果本身就是零,就要保留了。

	while (c[len - 1] == 0 && len > 1)
	{
		len--;
	}

全部代码

#include <iostream>
#include <string>
using namespace std;
const int N = 1e5;
string a, b;
int ra[N], rb[N], c[N];

int main()
{
	cin >> a;
	cin >> b;
	for (int i = 0; i < a.length(); i++)
	{
		ra[i] = a[a.length() - i - 1] - '0';
	}
	for (int i = 0; i < b.length(); i++)
	{
		rb[i] = b[b.length() - i - 1] - '0';
	}

	int len = a.length() + b.length();
	for (int i = 0; i < a.length(); i++)
		for (int j = 0; j < b.length(); j++)
		{
			c[i + j] += ra[i] * rb[j];
			c[i + j + 1] += c[i + j] / 10;
			c[i + j] = c[i + j] % 10;
		}
	while (c[len - 1] == 0 && len > 1)
	{
		len--;
	}
	for (int i = 0; i < len; i++)
		cout << c[len - i - 1];
	return 0;
}

“居然用python都不能逃课,python还是有极限的。” 

高精度a的b次方 

00001
00002
00004
00008
00016

 上面就是求2的4次方的过程。我们先开一个数组最后一位放1,该数组就相当于是1。然后for循环指数次即4次,让数组中的每个数都乘以底数2,然后如果数组里面有数字是大于等于10的,就取模,进位。

全部代码

#include <iostream>

using namespace std;
const int N = 1e3;
int num[N];
int a, b;

int main()
{
  cin >> a;
  cin >> b;
  num[N - 1] = 1;
  for (int i = 0; i < b; i++)
  {
    for (int i = 0; i < N; i++)
    {
      num[i] *= a;
    }
    for (int i = N - 1; i >= 0; i--)
    {
      if (num[i] >= 10)
      {
        num[i - 1] += num[i] / 10;
        num[i] = num[i] % 10;
      }
    }
  }
  int index = 0;
  while (num[index] == 0 && index < N - 1)
  {
    index++;
  }
  for (int i = index; i < N; i++)
    cout << num[i];

  return 0;
}

 

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HUTAC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值