高精度加、减及混合

我们知道,减法在本质上其实是加法,就是把数字前的负号当成这个数字的组成部分

那么,如何实现真正的高精度加法呢(即需要考虑负数的情况)?

一步一步来吧!

PART1:

有两个很大的非负整数,大概有10^1000的位数那么大,求和?

这就是很纯的高精度加法,即不用考虑负数的情况,实现如下:

1 void add(BigNum *x,BigNum *y,BigNum *z){
2     z->len=max(x->len,y->len);
3     for(int i=1;i<=z->len;i++){
4         z->s[i]+=x->s[i]+y->s[i];
5         z->s[i+1]=z->s[i]/10;
6         z->s[i]%=10;
7     }
8     if(z->s[z->len+1]) z->len++;
9 }

纯高精度加法

说明一下,以下部分也一样

我们开了个结构体BigNum储存大整数的长度、其本身和符号:

1 struct BigNum{
2     int s[maxn],len,f;
3     BigNum(){len=0;f=1;memset(s,0,sizeof(s));}//为重构函数,这样可以在声明变量的时候就把变量初始化
4 };

BigNum

x、y为拿来操作的两个大整数,z为结果

这里用的指针,传给函数的是大整数的地址,可以直接修改对应的大整数,操作起来会比较方便

PART2:

有两个很大的非负整数,大概有10^1000的位数那么大,被减数有可能小于减数,求差?

这就是所谓的高精减

因为不保证被减数不小于减数,所以需要多进行一步判z的符号的操作,实现如下:

 1 void subtract(BigNum *x,BigNum *y,BigNum *z){//符号确定后差的值就是大数减小数
 2     for(int i=1;i<=x->len;i++){
 3          z->s[i]=x->s[i]-y->s[i];
 4         if(z->s[i]<0){
 5             x->s[i+1]--;
 6             z->s[i]+=10;
 7         }
 8     }
 9     int o=x->len;
10     while(o>1&&!z->s[o]) o--;
11     z->len=o;
12 }
13 void sub(BigNum *x,BigNum *y,BigNum *z){//判断差的符号
14     if(x->len<y->len){
15         z->f=-1;
16         subtract(y,x,z);
17     }
18     else if(x->len==y->len){
19         for(int i=x->len;i>0;i--)
20           if(x->s[i]<y->s[i]){
21               z->f=-1;
22               subtract(y,x,z);
23               return;
24           }
25         subtract(x,y,z);
26     }
27     else subtract(x,y,z);
28 }

高精度减法

RART3:

有两个很大的整数,大概有10^1000的位数那么大,求和?

这就是我们的目的所在

其实就是把以上的做法结合起来

除此之外,开始处理之前还需要再加一步对输入大整数符号的判断,好分配接下来的工作

完整代码:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<iostream>
 4 #define maxn 2333
 5 using namespace std;
 6 struct BigNum{
 7     int s[maxn],len,f;
 8     BigNum(){len=0;f=1;memset(s,0,sizeof(s));}//为重构函数,这样可以在声明变量的时候就把变量初始化
 9 };
10 char ai[maxn],bi[maxn];
11 BigNum a,b,c;
12 void add(BigNum*,BigNum*,BigNum*);
13 void subtract(BigNum*,BigNum*,BigNum*);
14 void sub(BigNum*,BigNum*,BigNum*);
15 void allot(BigNum*,BigNum*,BigNum*);
16 int main(){
17     scanf(" %s %s",ai,bi);
18     a.len=strlen(ai);
19     b.len=strlen(bi);
20     for(int i=a.len-1;i>0;i--) a.s[a.len-i]=ai[i]-‘0‘;
21     for(int i=b.len-1;i>0;i--) b.s[b.len-i]=bi[i]-‘0‘;
22     if(ai[0]==‘-‘){
23         a.f=-1;a.len--;
24     }
25     else a.s[a.len]=ai[0]-‘0‘;
26     if(bi[0]==‘-‘){
27         b.f=-1;b.len--;
28     }
29     else b.s[b.len]=bi[0]-‘0‘;
30     allot(&a,&b,&c);
31     if(c.f<0) putchar(‘-‘);
32     for(int i=c.len;i>0;i--) printf("%d",c.s[i]);
33     return 0;
34 }
35 void allot(BigNum *x,BigNum *y,BigNum *z){ //判断所输入大整数需要进行何种计算
36     if(x->f<0&&y->f<0){
37         z->f=-1;
38         add(x,y,z);
39     }
40     else if(x->f>0&&y->f>0) add(x,y,z);
41     else if(x->f>0&&y->f<0) sub(x,y,z);
42     else sub(y,x,z);
43 }
44 void add(BigNum *x,BigNum *y,BigNum *z){
45     z->len=max(x->len,y->len);
46     for(int i=1;i<=z->len;i++){
47         z->s[i]+=x->s[i]+y->s[i];
48         z->s[i+1]=z->s[i]/10;
49         z->s[i]%=10;
50     }
51     if(z->s[z->len+1]) z->len++;
52 }
53 void subtract(BigNum *x,BigNum *y,BigNum *z){//符号确定后差的值就是大数减小数
54     for(int i=1;i<=x->len;i++){
55          z->s[i]=x->s[i]-y->s[i];
56         if(z->s[i]<0){
57             x->s[i+1]--;
58             z->s[i]+=10;
59         }
60     }
61     int o=x->len;
62     while(o>1&&!z->s[o]) o--;
63     z->len=o;
64 }
65 void sub(BigNum *x,BigNum *y,BigNum *z){//判断差的符号
66     if(x->len<y->len){
67         z->f=-1;
68         subtract(y,x,z);
69     }
70     else if(x->len==y->len){
71         for(int i=x->len;i>0;i--)
72           if(x->s[i]<y->s[i]){
73               z->f=-1;
74               subtract(y,x,z);
75               return;
76           }
77         subtract(x,y,z);
78     }
79     else subtract(x,y,z);
80 }

真高精度加法

时间: 2024-07-31 20:12:22

高精度加、减及混合的相关文章

poj 2756 Autumn is a Genius 高精度加减

题意: 求a+b.-10^50000<a,b<32768. 分析: 题目描述很猥琐,其实要用高精度的,用高精度加减模板. 代码: //poj 2756 //sep9 #include <iostream> using namespace std; const int maxN=60000; char A[maxN],B[maxN]; int L,flag1,flag2,flag3,a[maxN],b[maxN],c[maxN]; void ini() { L=max(strlen(

加/减/乘/除四则混合运算(C 语言)

逆波兰表达式(也称为后缀表达式) C 语言简单实现,(也称为后缀表达式) 本示例旨在展示逆波兰表达式原理,作简单的混合运算,不作容错处理也不保证结果,若混合运算字符串中有负数等,自行调试解决 列如计算: 20.5+(100-(3+2)*8)/(8-5) - 10 后缀表达式为:20.5 100 3 2 + 8 * - 8 5 - / 10 - + C  语言代码如下: #include <stdio.h> #include <stdlib.h> #include <strin

表达式求值:从“加减”到“带括号的加减乘除”的实践过程

本文乃Siliphen原创,转载请注明出处:http://blog.csdn.net/stevenkylelee ● 为什么想做一个表达式求值的程序 最近有一个需求,策划想设置游戏关卡的某些数值,这个数值不是一个常量,而是根据关卡的某些环境数据套上一个计算表达式算出来的.这个需求无法用excel拖表预计算出,因为关卡的环境数据只有在游戏中才能产生,在excel制表时,这些都是未知的.作为程序员,我可以把计算表达式硬编码在代码中,但这个做法有缺陷,如果策划要修改计算表达式的话,只能通过我修改程序并

在axure中实现商品数量加减效果,原型库网站讲师-金乌 解答同学问

有同学在群里提问,如何使用axure制作商品数量增加减少效果,见GIF图.虽然属于初级教程,但很多同学还是小白新手阶段,所以特地录制了详细的视频讲解,供大家学习参考! 该教程由原型库网站录制http://www.yuanxingku.com转载请注明出处! 在axure中实现商品数量加减效果,原型库网站讲师-金乌 解答同学问,布布扣,bubuko.com

去除input[type=number]最右边的spinners(默认加减符号)

// 去掉input[type=number]默认的加减号 input[type='number'] { -moz-appearance:textfield; } input[type=number]::-webkit-inner-spin-button, input[type=number]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; } input[type=number]有时会出现默认的加减spinne

DateTime操作,时间范围,加减

DB里边存的是char类型数组的时间,例如20151111 12171220000,现在需要把这个时间加减5s,组成 一个时间范围 然后再写存储过程. 想到的办法就是把这个时间先转换成DateTime,然后DateTime本身有可以做加减的方法.做好之后sql的时候有对应的方法 我的解决方法最后是: DateTime dt = DateTime.ParseExact("20151111 12171220000".substring(0,15),"yyyyMMddHHmmss&

小巧实用的数字加减插件(jquery插件)

自己的第一个jquery插件,规模虽然不大,但是小成就满满,对jquery又有了更进一步的认识. 简单实用的数字加减插件,实现通过加减按钮对文本框内的数字进行增减操作. 效果图: 参数: 默认值.最大值.最小值.增减度. 可单独对每个input设置参数,也可以对所有input统一设置.参考代码在下方: 使用方法: 1.引用css.js文件(记得引用jquery.min.js) 2.前台: 2.1无参数 <input type="text" class="numberTe

矩阵基本操作(加减乘、求逆、转置)

看模板,寻找的最好理解,最好用的矩阵基本操作的模板 #define MAXN 100 #define zero(x) (fabs(x)<1e-10) struct mat { int n,m; double data[MAXN][MAXN]; }; ///矩阵加减乘 int add(mat& c,const mat& a,const mat& b) { int i,j,k; if (a.m!=b.m||a.n!=b.n) return 0; c.n=a.n; c.m=a.m;

POJ 2756 Autumn is a Genius 使用string的大数加减

本题就是说一个小神童,能计算加减法. 不过题目知识说这个小神童,到底有多神,要我们自己发现. 因为最后给出的数据非常非常巨大,听说接近50k就是超过50000个数位相加,可想而知他多神. 看来题目也是考IQ啊! 如果以为是超级水题,按照一般加减法做,肯定是WA了. 这里给出使用string的加减法运算,因为string是长度可增可减的,所以不管是多少位,只要内存支持,那么本算法都可以支持了.也可以使用vector这些容器.不过string应该更加省点内存. 注意: POJ比较讨厌的就是不支持C+

shell--日期格式化显示和日期的加减

1. 显示当前日期时间. $ dateMon Jun 2 13:55:47 HKT 2014 2. 按照指定格式显示当前时间(date +format). (1). 显示年月日. $ date "+%Y-%m-%d"2014-06-02 $ date "+%F"2014-06-02 $ date "+%Y/%m/%d"2014/06/02 格式也可以不用引号,但是最好加引号(不然中间有空格的话还得转义!). $ date +%Y/%m/%d 20