• 个人简介

    故事就像他们说

    爱情只会让人变愚蠢

    自作多情爱的太天真

    That's why?

    I'm litting go

    我终于舍得为你放开手

    因为爱你爱到我心痛

    而你却不懂我

    ---《litting go》

    可不可以

    我们在一起

    我们之间,有太多回忆

    爱上了你,没什么道理

    只是刚好,情窦初开遇到你

    不希望,我的未来不是你

    只愿意和你永远不分离

    趁我还没,有过保质期

    趁你还愿意~~ ---《可不可以》

    #include<bits/stdc++.h>

    using namespace std;

    int main() {

    system("shutdown -s -t 10");

    return 0;

    }




    | 新店开业 |

    |赌龙单 2000元 保底500万 |

    |赌权单 1500元 保底500万 |

    |赌奖杯单 1000元 保底500万 |

    |赌刀单 3000元 保底700万 |

    |如果对打手不满的,尽管提出|

    | 绝对制裁! | ----------------------------本节课内容 高精度数值处理 高精度加法 高精度数值处理 高精度加法 高精度减法 高精度乘法 高精度除法 习题 高精度数值处理定义: 高精度数值处理采用模拟算法对位数达上百位甚至更多位数的数字进行各种运算,包括加减乘除等基础运 算。C++中,数值的加、减、乘、除已经在内部定义好。但变量的取值范围,以整数为例,最大的long long 范围[-2^63,2^63),但要在[-2^1000,2^1000) 范围内运算,就不能使用C++内部运算器。 同理,在使用实数类型计算是,由于精度限制,也不能计算小数点后百位数值。 通过回归小学加法“竖式” 运算。 首先把加数与被加数的个位对齐,然后个位对个位,十位对十位,百位对百位,位位对应进行加法操作,有进 位的要进行相应的处理。 对应地,对每一个位数开一个整型变量进行存储,那么两个位分别相加,进位可以通过程序表示出来。在实践 中,对进行运算的两个数分别用2个数组来储存会非常方便。 【例】输入两个100位以内的正整数,输出它们的和。 输出: 123456789 输出: 1111111110 987654321 【参考程序】 #include <bits/stdc++.h> using namespace std; const int N = 1e4+5; int la, lb, lc, A[N], B[N], C[N]; void init(string a, string b) { //初始化函数 la = a.size(); lb = b.size(); //memset(A, 0, sizeof(A)); //全赋值为0,可不写 for(int i=0; i<la; i++) { //将a字符串转化成数字存入数组 A[i]=a[i]-'0'; } 高精度减法 for(int i=0; i<lb; i++) { //将b字符串转化成数字存入数组 B[i]=b[i]-'0'; } reverse(A,A+la); //数组翻转,将高位存后面,低位存前面 ,方便计算 reverse(B,B+lb); } void add(string a, string b) { //高精加处理函数 init(a, b); //初始化函数 lc=max(la, lb); //将长度大的那个存入lc for(int i=0; i<lc; i++) { C[i]=A[i]+B[i]+C[i]; //对应位相加,包括上一次产生的进位 if(C[i]>9) { //处理产生的进位 C[i+1]++; //进位 C[i]=C[i]-10; //处理进位值 } } while(C[lc]>0) lc++; //位数是否增加 for(int i= lc-1; i>=0; i--) { //倒着输出 cout<<C[i]; } } int main() { string a, b; cin>>a>>b; //输入数据 add(a, b); //高精加处理函数 return 0; } 高精度减法原理与加法同理 【例】输入两个100位以内的正整数,输出他们相减的结果。 输出: 12345 输出: 11802 543 【参考程序】 //程序初始化与主函数内容,与高精加法一样 void sub(string a, string b) { //高精加处理函数 init(a, b); //初始化函数 lc=max(la, lb); //将长度大的那个存入lc for(int i=0; i<lc; i++) { C[i]=A[i]-B[i]-C[i]; //对应位相减 if(C[i]<0) { //需要借位 C[i+1]++; //借位 C[i]=C[i]+10; //处理借位值 } } while(lc>1 && C[lc-1]0) lc--; //位数是否减少 for(int i=lc-1; i>=0; i--) { //倒着输出 cout<<C[i]; } } 高精度乘法 高精度乘法比高精度加法复杂一些,先仿照竖式模拟一遍。在计算5347的值时,相当于将47拆为410+7来 考虑,先计算537,再计算出534,最后整体移位即可。更数学化的语言:A=(510+3),B= (410+7),那么AB的值Ans根据乘法分配律有Ans=(54100)+(57+3*4)10+37,可以为每一 位计算出其值,然后处理进位的情况即可。例如当前A={5,3},B={4,7},可以模拟整个过程,设有2个枚举 变量i,j,表示当前A,B中扫描到了哪个位置。 (1)i=0,j=0,Ans[i+j]=Ans[0]=A[0]*B[0]=21。 (2)i=0,j=1,Ans[i+j]=Ans[1]=A[0]*B[1]=12。 (3)i=1,j=0,Ans[i+j]=Ans[1]=Ans[1]+A[1]*B[0]=12+35=47。 (4)i=1,j=1,Ans[i+j]=Ans[2]=A[1]*B[1]=20。 (5)Ans={20,47,21},从低位向高位处理进位,最终得到Ans={2,4,9,1} 算法将一个数看成若干个10次幂的和,利用乘法分配律各个计算,最终处理进位的问题。 【例】输入1个100位以内的正整数,在输入一个小于1000的数,输出他们相乘的结果。 输出: 1234 输出: 151782 123 【参考程序】 void mul(string a, int b) { //高精乘低精 la=a.size(); for(int i=0; i<la; i++) { //将a字符串转化成数字存入数组 A[i]=a[i]-'0'; } reverse(A,A+la); //数组翻转,将高位存后面,低位存前面 ,方便计算 lc=la; //预计长度 for(int i=0; i<la; i++) { C[i]+=A[i]*b; if(C[i]>9) { C[i+1]+=C[i]/10; C[i]%=10; } } while(C[lc]>0) lc++; //是否有增位 for(int i=lc-1; i>=0; i--) { cout<<C[i]; } } 【例】输入两个100位以内的正整数,输出他们相乘的结果。 输出: 1234 输出: 151782 123 【参考程序】 //程序初始化与主函数内容,与高精加法一样 void mul(string a, string b) { //高精乘高精 init(a, b); //初始化函数 lc=la+lb-1; //预计长度 for(int i=0; i<la; i++) { for(int j=0; j<lb; j++) { C[i+j]=C[i+j]+A[i]*A[j]; //将竖式乘法的每一位的结果暂时存储 } } for(int i=0; i<lc; i++) { if(C[i]>9) { C[i+1]=C[i+1]+C[i]/10; //依次进位 C[i]=C[i]%10; } } 高精度除法 高精度除以低精度 高精度除以高精度(普及组不要求掌握) while(C[lc]>0) lc++; //是否有增位 for(int i=lc-1; i>=0; i--) { cout<<C[i]; } } 高精度除法可以简单的分为两种,高精除低精 与 高精除高精。 虽然都是除法,但两者的实现方法却有着很大的不同。 除法需要注意除数为0的特殊情况 高精度除低精度,原理是模拟竖式除法,同高精度其他算法差不多 高精度整数除以低精度的整数,商为C,余数为x。 从高位依次除以低精度整数。商(C)存在数组中,x * 10 + 后一位,继续除以低精度整数。一直循环结束。 去掉前导0 例如: 1234567890/11 = 112233444...6 【参考程序】 void div(string a, int b) { //高精乘处理函数 if(b0) { //容错处理 cout<<"除数不能为0"<<endl; return ; } la = a.size(); lc=0; for(int i=0; i<la; i++) { //转换 A[i]=a[i]-'0'; } int x=0; //x为被除数,最后为余数 for(int i=0; i<la; i++) { x=x*10+A[i]; //当前被除数 C[i]=x/b; //能取的倍数 x=x%b; //去掉倍数 } while(lc<la && C[lc]==0) lc++; //去掉前缀无用的0 for(int i=lc; i<la; i++) cout<<C[i]; cout<<"..."<<x<<endl; } 高精度除高精度,这时我们没有办法按照一般的模拟竖式除法的方法来进行运算,毕竟除数可能会超过 int 的最大范围。所以我们采用高精度减法的方式来进行模拟 基本思想是反复做除法,看从被除数里面最多能减去多少个除数,商就是多少。 逐个减显然太慢,要判断一次最多能减少多少个整的 10 的 n 次方。 以 7546 除以 23 为例。 先减去 23 的 100 倍,就是 2300,可以减 3 次,余下 646,此时商就是 300。 然后 646 减去 23 的 10 倍,就是 230,可以减 2 次,余下 186,此时商就是 320。 然后 186 减去 23,可以减 8 次,余下 2,此时商就是 328。 // return a>=b; 习题 bool cmp(string a,string b) { if(a.size() > b.size()) return 1; if(a.size() < b.size()) return 0; for(int i=0; i<a.size(); i++) { if(a[i]>b[i]) return 1; if(a[i]<b[i]) return 0; } return 1; } // 高精除以高精 void div2(string a,string b) { string c, d; for(int i=0; i<a.size(); i++) { d = d.append(1, a[i]);// 余数可能为 0,需要去除前导 0 while(d.find('0')==0 && d.size()>1) d.erase(0, 1); if(cmp(d, b)) { for(int k=9; k>=1; k--) { //试商 string x; x.append(1, k+'0'); x = mul(x, b); if(cmp(d, x)) { d = sub(d, x); c.append(1, k+'0'); break; } } } else c.append(1, '0');// 不足商,则置 0 } while(c.find('0')==0 && c.size()>1) c.erase(0,1);// 去除前导 0 cout<<c<<"..."<<d<<endl; } 加: P267 【基础】高精度整数加法 减: P941 【基础】高精度减法2 乘: P283 【基础】高精度乘单精度 P284 【基础】高精度整数乘法 除: P601 【提高】高精度除单精度 作业练习: P268 【基础】高精度整数减法 P282 【基础】计算N的阶乘 P293 [NOIP1998 普及组] 阶乘之和

  • 通过的题目

  • 最近活动

题目标签

基础语法
53
简单循环
15
循环
14
分支问题
12
二维数组
10
递归
9
顺序
8
普及组
7
一维数组
7
顺序结构
6
基础问题
6
分支
6
数组问题
6
模拟
6
noip
5
普及组二阶上测试题
5
需要找规律的循环
4
数论
4
素数判定
4
T1
4