大数运算(C++)
来源:互联网 发布:谷阿莫华尔街之狼 知乎 编辑:程序博客网 时间:2024/04/28 19:45
大数就是指十几位,几十位或者几百位的数字,反正对于这样的数,任何计算机本身的变量类型(int,double,甚至long long)都表示不了。怎么存?最常用的就是用字符串string或者向量vector,然后的问题自然是要实现大数的四则运算。
大数加法
加法的实现很简单,就是从低位开始,模拟加法的计算过程,需要注意的就是计算过程中产生的进位。
string实现大数加法:
string BigIntPlus(string s1, string s2){ //把较长的数给s1,方便写程序 if (s1.size() < s2.size()) { string tmp = s2; s2 = s1; s1 = tmp; } //从低位开始,模拟加法的过程,注意每次加法的进位即可 for (int i = s1.size()-1, j = s2.size()-1; i >= 0; i--, j--) { s1[i] = s1[i] + (j >= 0 ? s2[j] - '0' : 0); if (s1[i] > '9')//表示有进位 { s1[i] -= 10; if (i) s1[i - 1]++; else s1 = '1' + s1;//i=-1,表示超过了原来的长度,利用字符串加法 } } return s1;}
大数减法
大数减法虽然看起来也就是模拟做减法的过程,但实际上比加法复杂的多。网上很多所谓的大数减法的程序,要么只能计算结果为正数的情况,要么2225-2227算下来结果显示-0002,什么鬼嘛,等于-2呀。
1.string实现大数减法:
//用来清除数字字符串前多余的0string eraseZero(string s){ if (s.size() <= 1) return s; if (*s.begin() != '0') return s; s.erase(s.begin()); return eraseZero(s);}//返回s1-s2的值//为了方便写程序,我们先保证计算的结果是正数,最后看情况是否需要转负数string BigIntMinus(string s1, string s2){ bool tag = false;//用来标记s1 s2是否发生了交换 if (s1.size() < s2.size() || (s1.size()==s2.size() && s1 < s2)) { tag = true; string tmp = s2; s2 = s1; s1 = tmp; } for (int i = s1.size()-1, j = s2.size()-1; i >= 0; i--, j--) { if (j>=0){ if (s1[i] < '0' || s1[i] < s2[j])//需要借位 { s1[i] = s1[i] + 10 - ((j < 0) ? 0 : s2[j] - '0'); s1[i - 1]--; continue; } } s1[i] = s1[i] - ((j<0) ? 0 : s2[j] - '0'); } //处理计算结果字符串前面多余的0,比如0005应该显示5 string result = eraseZero(s1); if (tag) result = '-' + result; return result;}
虽然我们用string可以实现大数减法,但写程序的过程总是很不舒服的。因为我们从头到尾都要记得我们处理的是字符’0’…..’9’,而不是真正的数字0,1……9。
大数乘法
大数的乘法就有多种算法思想。主要有分治法、快速傅里叶变换FFT法、中国剩余定理、简单方法(模拟乘法的过程)。前面几种看起来就NB,被吓住的赶紧去百度一下,我这里还是简单研究下简单方法……
这里我们从LeetCode的一道题目说起:Multiply Strings
这里我直接贴高票答案的代码,因为实在写的太好了,我自己写的不堪入目。
string multiply(string num1, string num2) { string sum(num1.size() + num2.size(), '0'); for (int i = num1.size() - 1; 0 <= i; --i) { int carry = 0; for (int j = num2.size() - 1; 0 <= j; --j) { int tmp = (sum[i + j + 1] - '0') + (num1[i] - '0') * (num2[j] - '0') + carry; sum[i + j + 1] = tmp % 10 + '0'; carry = tmp / 10; } sum[i] += carry; } size_t startpos = sum.find_first_not_of("0"); if (string::npos != startpos) { return sum.substr(startpos); } return "0";}
GMP
其实关于大数运算,早就有高精度计算库GUN的GMP(Arithmetic without limitations)
GMP,我们只需要调用就行了。
0 0
- 大数运算 (C++)
- 大数运算(C++)
- 大数运算实现(C++)
- 大数运算(c、java)
- c语言版大数计算器(实现大数的加减乘除运算)
- RSA与大数运算(C语言)
- 大数的运算(加减乘除)C代码
- 大数运算模板(C语言)
- 大数运算-加法(C/C++实现)
- 大数运算-减法(C/C++实现)
- 大数运算(大数之和)
- 大数的加减乘除运算(C++)
- 【C++】C++大数的运算
- C语言大数运算-大数运算库篇
- 大数运算之100的阶乘(C语言实现)
- C语言探秘之大数运算(转)
- 大数a^b%c(快速幂运算)模板
- 大数的运算实现(C++、字符串)、Git使用示例
- 自定义连接池
- pinyin4j使用示例(支持多音字)
- android studio svn设置忽略文件
- 按键监听实现Fragment跳转
- UVA10600 ACM Contest and Blackout (次小生成树)
- 大数运算(C++)
- VIM命令模式下命令
- 静态链接库 VS 动态链接库
- 二分_E
- set集合容器
- 线程池的几种常见的创建的方式
- springMVC+hibernate+springdata+querydsl搭建框架(优缺点分析+springdata介绍)
- Android控件属性
- just my first blog