首页 > 其他分享 >(二十三)高精度运算

(二十三)高精度运算

时间:2024-07-12 17:55:17浏览次数:10  
标签:include 运算 高精度 int 2.3 2.2 MOD 二十三

文章目录

一、前言

这次,高精度帖子,它来了!点个赞
请添加图片描述

二、正文

2.1 什么是高精度?

还记得C++的类型吗?int类型最多可以存储10位数(到十亿),就连long long类型最多也只能存储20位数(到一千京),因此short类型的存储最大值可怜得只有5位(到一万),而强大的高精度比long long类型大好几十倍。因为这种数很大,因此有一种叫法——大数。高精度数没有办法直接加减乘除,应该怎么办呢?

2.2 高精度加

2.2.1 理论

接着我们想一想加法计算原理,这是小学一年级的知识,没有forget吧?
相同数位对齐,从右往左相同数位相加,结果大于10的要进1

在这里插入图片描述
在C++数组中,我们刚好可以实现加减。理论成功,实践开始

2.2.2 怎么敲代码?

2.2.2.1 存储两个数

我们可以使用string类型进行存储

string _a, _b; 
cin >> _a >> _b; 
2.2.2.2 倒序存入数组

我们都知道,相同数位要对齐,那么如何对齐呢?我们可以换位思考:将两个高精度数字颠倒过来刚好数位对齐。以前讲过,颠倒string的代码:reverse(str.begin(), str.end()); 另外,其实#include <string>是包含在#include <iostream>中的,因此我们只需要导入两个库:

#include <iostream> //string包含在里面
#include <algorithm> //别把我forget了,reverse()函数在我里面
#include <cmath> //我要创建大小合适的数组(现在没有写到vector)

因此现在我们需要倒序存入数组,要把ASCII码转换为数字!
建议记住ASCII码中的一些重点字符的编码

字符ASCII
'0'48
'A'65
'a'97
reverse(_a.begin(), _a.end()); 
reverse(_b.begin(), _b.end()); 
const int MOD = max(_a.length(), _b.length()); //可以使用MOD来代替,简化代码
int a[MOD] = {}; //数组获取越界要乱码 
int b[MOD] = {}; 
int c[MOD+1] = {}; //有可能会在最高位进位,所以要+1
for(int i=0; i<_a.length(); i++) 
	a[i] = _a[i] - 48; //48是'0'的ASCII码 
for(int i=0; i<_b.length(); i++)
	b[i] = _b[i] - 48; 
2.2.2.3 开始计算

计算时我们考虑的情况很多

  1. 不进位,检验是否成功输入以下数据(通过率90%)
输入
12
23
输出
35
  1. 进了位,但没有突破原来的最高位。检验输入以下数据(通过率60%)
输入
16
59
输出
75
  1. 进了位,且突破原来的最高位。检验输入以下数据(通过率20%)
输入
999
111
输出
1110
  1. 结果为0的情况(通过率20%)
输入
99
99
输出
0

计算不难,难在细节。应该用=还是+=号要想清楚,不然很容易就WA

for(int i=0; i<MOD; i++) {
	c[i] += a[i]+b[i]; //用+=才能接受进位
	c[i+1] = c[i]/10; //用=或+=都行,因为进位前这些数全是0
	c[i] %= 10; //用%=没有理由
}
2.2.2.4 结果更改

我们计算后最终的前导0都要删,但加法一个前导0都没有,为什么呢?别忘了刚才的MOD+1,为了情况3

reverse(c, c+MOD+1); 
string _c; 
bool flag = true;  
for(int i=0; i<=MOD; i++) {
	if(!(c[i]==0&&flag)) {
		flag = false; 
		_c += c[i]+48; 
	}
}
if(_c.empty()) _c = "0"; 
cout << _c; 
2.2.2.5 最终代码
#include <iostream> //你写#include <bits/stdc++.h> 没有人拦着你 
#include <algorithm>
#include <cmath>
using namespace std; 
int main() {
	string _a, _b; 
	cin >> _a >> _b; 
	reverse(_a.begin(), _a.end()); 
	reverse(_b.begin(), _b.end()); 
	const int MOD = max(_a.length(), _b.length()); //可以使用MOD来代替
	int a[MOD] = {}; //数组获取越界要乱码 
	int b[MOD] = {}; 
	int c[MOD+1] = {}; //有可能会在最高位进位,所以要+1
	for(int i=0; i<_a.length(); i++) 
		a[i] = _a[i] - 48; //48是'0'的ASCII码 
	for(int i=0; i<_b.length(); i++)
		b[i] = _b[i] - 48; 
	for(int i=0; i<MOD; i++) {
		c[i] += a[i]+b[i]; 
		c[i+1] = c[i]/10; 
		c[i] %= 10; 
	}
	reverse(c, c+MOD+1); 
	string _c; 
	bool flag = true;  
	for(int i=0; i<=MOD; i++) {
		if(!(c[i]==0&&flag)) {
			flag = false; 
			_c += c[i]+48; 
		}
	}
	if(_c.empty()) _c = "0"; 
	cout << _c; 
	return 0; 
}

2.3 高精度减

2.3.1 理论

就是减法竖式
在这里插入图片描述
可是在这里有正数减正数等于负数的情况,怎么办呢?
a − b = − ( b − a ) a-b=-(b-a) a−b=−(b−a)
我们可以利用这个公式来解决这个问题

2.3.2 怎么敲代码?

2.3.2.1 存储

和加法一样的,但是要将两个结果为负数的数调换,为了判断两个数哪一个大,我们要这么写

string _a, _b, _c; 
cin >> _a >> _b; 
if(_a.length()<_b.length()) {
	_c += "-"; 
} else if(_a.length()==_b.length()) {
	for(int i=0; i<_a.length(); i++) {
		if(_a[i]<_b[i]) {
			swap(_a, _b); 
			_c += "-";  
			break; 
		} else if(_a[i]>_b[i]) {
			break; 
		}
	}
}
2.3.2.2 倒序存入数组

和加法是一样的

2.3.2.3 计算

计算就不一样了。同样的,把-==搞清楚,不搞清楚很容易错

  1. 不退位,检验是否成功输入以下数据(通过率90%)
输入
90
20
输出
70
  1. 退了位,但>0。检验输入以下数据(通过率60%)
输入
98
89
输出
9
  1. 退了位,且成为负数。检验输入以下数据(通过率60%)
输入
10
12
输出
-2
  1. 结果为0的情况(通过率20%)
输入
99
99
输出
0
for(int i=0; i<MOD; i++) {
	c[i] += a[i] - b[i]; 
	if(c[i]<0) {
		c[i] += 10; 
		c[i+1] -= 1; 
	}
}
2.3.2.4 结果更改

一样的

2.3.2.5 全部代码
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
using namespace std; 
int main() {
	string _a, _b, _c; 
	cin >> _a >> _b; 
	if(_a.length()<_b.length()) {
		_c += "-"; 
	} else if(_a.length()==_b.length()) {
		for(int i=0; i<_a.length(); i++) {
			if(_a[i]<_b[i]) {
				swap(_a, _b); 
				_c += "-";  
				break; 
			} else if(_a[i]>_b[i]) {
				break; 
			}
		}
	}
	reverse(_a.begin(), _a.end()); 
	reverse(_b.begin(), _b.end()); 
	const int MOD = max(_a.length(), _b.length()); 
	int a[MOD] = {}; 
	int b[MOD] = {}; 
	int c[MOD+1] = {}; 
	for(int i=0; i<_a.length(); i++) 
		a[i] = _a[i] - 48; 
	for(int i=0; i<_b.length(); i++) 
		b[i] = _b[i] - 48; 
	for(int i=0; i<MOD; i++) {
		c[i] += a[i] - b[i]; 
		if(c[i]<0) {
			c[i] += 10; 
			c[i+1] -= 1; 
		}
	}
	reverse(c, c+MOD+1); 
	bool flag = true;  
	for(int i=0; i<=MOD; i++) {
		if(!(c[i]==0&&flag)) {
			flag = false; 
			_c += c[i]+48; 
		}
	}
	if(_c.empty()) _c = "0"; 
	cout << _c; 
	return 0; 

}

2.3 高精度乘

2.3.1 理论

乘法竖式记得吧,但是这个式子你们知不知道(A和B是两个因数,C是积)
A i + B j = C i + j A_{i} + B_{j} = C_{i+j} Ai​+Bj​=Ci+j​
在这里插入图片描述

2.3.2 代码

#include <bits/stdc++.h> 
using namespace std; 
int main() {
    string as, bs; //原来的两个字符串
    cin >> as >> bs; 
    int lena = as.size(); 
    int lenb = bs.size(); 
    int len = lena + lenb; 
    int a[lena]={}, b[lenb]={}, c[len]={}; 
    for(int i=0; i<lena; i++) a[lena-i-1] = as[i] - 48; //倒序存入数组中
    for(int i=0; i<lenb; i++) b[lenb-i-1] = bs[i] - 48; 
    for(int i=0; i<lena; i++) {
        int x = 0; //x:进位
        for(int j=0; j<lenb; j++) {
            c[i+j] += a[i] * b[j] + x; 
            x = c[i+j] / 10; 
            c[i+j] %= 10; 
        }
        c[i+lenb] = x; 
    }
    while(c[len-1]==0&&len>1) len --; //删除前导0且除去结果为0的情况
    for(int i=len-1; i>=0; i--) cout << c[i]; 
    return 0; 
}

2.4 高精度除以低精度

2.4.1 理论

除法竖式懂吧
在这里插入图片描述

2.4.2 代码

#include <bits/stdc++.h> 
using namespace std; 
int main() {
    string a1; 
    int b; 
    cin >> a1 >> b; 
    int lena = a1.size(); 
    int a[lena+1] = {}, c[lena+1] = {}; 
    for(int i=0; i<lena; i++) 
        a[i+1] = a1[i] - 48; 
    int x = 0; //余数 
    for(int i=1; i<=lena; i++) {
    	int t = 10*x+a[i]; 
        c[i] = t/b; 
        x = t%b; 
    }
    int lenc = 1; 
    while(c[lenc]==0 && lenc<lena) lenc++; 
    for(int i=lenc; i<=lena; i++) 
        cout << c[i]; 
    return 0; 
}

三、结语

3.1 预览

3.2 一个“简单”的问题

你能结合类(class)和高精度运算完成一个类,要求:

  1. 名字为higpre
  2. 定义方式
    • higpre n; :定义高精度数
    • higpre n(Str); :定义高精度数,并赋值为Str
    • n.init(Str); :赋值为Str
  3. 重载符号+-*/=/前面写higpre类型的数,后面写int类型的数)
  4. 使用higpre::input()higpre::output()进行输入和输出

有兴趣的可以将代码直接发在评论区内(只发这个类的代码)
请添加图片描述

标签:include,运算,高精度,int,2.3,2.2,MOD,二十三
From: https://blog.csdn.net/2401_85898378/article/details/140370053

相关文章

  • 科普 | 3分钟读懂高精度时间同步
    通过上一期的内容我们知道北京时间作为我们国家的标准时间,是由中国科学院国家授时中心产生、保持和发播的。中国科学院国家授时中心位于陕西西安临潼,那北京时间诞生于这里,是怎么做到让全国人民都用上北京时间呢,大家又是通过什么手段和北京时间实现同步的呢?看完本期内容,相信你......
  • 08_Shell运算符
    08_Shell运算符一、算数运算符expr整数表达式#!/bin/bash#整数运算(expr只能整数运算)expr1+1expr1\*2expr2/1expr2-1expr3%2#结果接收要用``反引号result=`expr1+1`echo$result二、比较运算符2.1、整数比较运算符运算符说明......
  • Lingo学习(三)——工厂合并、运算符、内置函数
    一、工厂合并(一)工厂合并——生产二维矩阵【引入】sets:                                factory/1..6/:a;                  plant/1..8/:d;                    Cooperation(fact......
  • DW03D是一款用于锂离子/聚合物电池保护的高集成度解决方案。DW03D包含内部功率MOSFET
    一般概述    DW03D产品是单节锂离子/锂聚合物可充电电池组保护的高集成度解决方案。DW03D包括了先进的功率MOSFET,高精度的电压检测电路和延时电路。    DW03D具有非常小的TSS08-8的封装,这使得该器件非常适合应用于空间限制得非常小的可充电电池组应用。 ......
  • 衡庐浅析·C语言程序设计·第二章·运算符及其优先级关系(练习题一)
        本文适用于大学的期中期末考试、专升本(专接本、专插本)考试、408等考研预科。如有相关题目疑问或建议欢迎在评论区进行互动。    转载请标明出处。不知道大家有没有消化完第二章的内容。在这里我们将列出一些关于运算符及其优先级关系的课后练习题,方便大家......
  • 位运算
    a^b算法:快速幂。考虑一些经典的分类讨论:$b$为奇数,此时分解为$a^{\frac{b-1}{2}}\timesa^{\frac{b-1}{2}}\timesa$。$b$为偶数,此时分解为$a^{\frac{b}{2}}\timesa^{\frac{b}{2}}$。我们的边界为$a$,因为这是已经给出的。所以我们发现,每次$b$会减少一半,时间复......
  • 浙大数据结构慕课课后习题(02-线性结构2 一元多项式的乘法与加法运算)
    题目要求设计函数分别求两个一元多项式的乘积与和。输入格式:输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。输出格式:输出分2行,分别以指数递降方式输出乘积多项式以及和多项......
  • C语言学习笔记(03)——常用运算符
    基本运算符*/inta=b*10; CPU可能多个周期,甚至要利用软件的模拟方法去实现乘法inta=b+10; CPU一个周期可以处理/取整%取余一般使用/和%配合得到小数,一般/的结果得到的是整数,除非: floata,b,c,d; a=7/2; b=7.0/2; c=7/2.0; d=7.0/2.0; printf......
  • Javase-3.运算符
    3.运算符1.算术运算符1.基本运算符:加减乘除模(+-*/%)inta=2;intb=1;System.out.println(a+b);//3System.out.println(a-b);//1System.out.println(a*b);//2System.out.println(b/a);//0int/int结果还是int类型,而且会向下取整System.out.print......
  • Python运算符
    一、算数运算符1.分类算数运算符有“+”,“-”,“*”,“/”,“%”,“//”,“**”这7种“%”用来求余,它通常用来判定奇数偶数或者倍数“//”用来求商,它返回的是整数“**”用来求某个数的次方,例如m**n就是求m的n次方a,b=10,20r=a/bprint(a+b,a-b,a*b,r,type(r))pri......