在csdn看到有人提出关于大数加法的实现问题,想起在学数据结构时有个课程设计是“链表实现大整数的运算”,当时看到就畏惧,如今是跃跃欲试。便尝试去实现下,由于课本还托在楼管那,不了解具体的要求,就先用非链表形式实现之。STL中的string拿来用之,顺便熟悉下。后发觉比字符数组好用多了。对于内存管理应更透明,尽管动态地、随便用它。
在编程过程中,发觉写代码的正确率实在过低。有时尽管思想出来了,但是具体落实到编程上,却老是会有BUG。而其中问题往往是非逻辑性的,是些小毛病。有些甚至要添加大量的cout才得以调试成功。 希望多加练习,能花尽量少的时间,写出正确漂亮的代码!
关于大整数的运算,包括 +,-,*,/。其中大整数位数可以是max (int) 也即string容量。理所当然,先实现加减。+->->*>/。
其中除法实现最久了,起初用最简单的方法,循环减去除数,得出结果。单处理111111111111111111111111/1时,机子就卡那很久。太烂了!便想着换掉。后来用到手算时的思想。效率可以提高很多,至少可以基本满足要求:随便输入,都可较快得到结果。
望路过者有疑问或好的建议,可以交流一二,无比感激!
- //===========================
- //用string 处理大数的运算: +,-,*,/,...
- //Input: num1 + num2 //需要有间隔
- //Ouput: result
- // BY Kasmile
- #include <iostream>
- #include <string>
- using namespace std;
- string Operate(string a,string operation,string b);
- string Add(string a,string b);
- string Sub(string a,string b);
- bool Great(string a,string b);
- string Mul(string a,string b);
- string Div(string a,string b);
- int main()
- {
- string num1,num2;
- string operation,result;
- cout<<"please input the nums to compute... "<<endl;
- cin>>num1>>operation>>num2;
- result = Operate(num1,operation,num2);
- cout<<"The result is : "
- <<result
- <<endl;
- return 0;
- }
- string Operate(string a,string operation,string b)
- {
- char oper = operation[0];
- switch(oper)
- {
- case '+':
- return Add(a,b);
- break;
- case '-':
- return Sub(a,b);
- break;
- case '*':
- return Mul(a,b);
- break;
- case '/':
- return Div(a,b);
- break;
- default:
- cout<<"Error..."<<endl;
- }
- }
- string Add(string a,string b)
- {//加法
- if(a.size() < b.size())
- {//加数a 为字符串 较长
- a.swap(b);
- }
- int t = 0;//进位标志
- int i = a.size() - 1,j = b.size() - 1;
- for(;i > j; j++)
- {//先对齐位数
- b = "0" + b;
- }
- for(;i >= 0; i--,j--)
- {//处理到a的位数
- int b1 = b[i] - 48;
- int a1 = a[j] - 48;
- a1 = a1 + b1 + t;
- t = 0;
- a[j] = a1%10 + 48;
- if(a1 > 9)
- {
- t = 1;
- }
- }
- return t? "1" + a: a;
- }
- bool Great(string a,string b)
- {//大小比较,a >= b 返回 true, a < b 返回false
- if(a.size() > b.size())
- return true;
- else
- if(a.size() < b.size())
- return false;
- else
- {
- int i = 0;
- for(; i < a.size() && (a[i] >= b[i]); i++)
- {
- if(a[i] > b[i])
- return true;
- }
- if(i < a.size())
- return false;
- return true;
- }
- }
- string Sub(string a,string b)
- {//减法
- bool flag = 0;//正负标志
- if(!Great(a,b))
- {//a总为较大数
- a.swap(b);
- flag = 1;
- }
- int i = a.size() - 1,j = b.size() - 1;
- for(;i > j; j++)
- {//先对齐位数
- b = "0" + b;
- }
- int t = 0;//借位标志
- for(;i >= 0; i--,j--)
- {//处理到a的位数
- int b1 = b[j] - 48;
- int a1 = a[i] - 48 - t;
- int d = a1 - b1;
- t = 0;
- if(d < 0)
- {
- t = 1;
- d = d + 10;
- }
- b[j] =d + 48;
- }
- string::iterator iter = b.begin();
- for(; (iter + 1) != b.end() && (*iter == '0');)
- {//删除无效的首位0,最后一位留着...
- b.erase(iter);//自动后移
- }
- return flag? "-" + b: b;
- }
- string Mul(string a,string b)
- {//乘法.
- int total = b.size() - 1;
- string result;
- for(int n = total; n >= 0; n--)
- {//从b的个位数 开始...
- string temp = "0";
- int add_num = b[n] - 48;
- for(;add_num > 0; add_num--)
- {//a累加add_num 次
- temp = Add(temp,a);
- }
- for(int i = 1; i <= total - n; i++)
- {//补0
- temp += "0";
- }
- result = Add(temp,result);
- }
- return result;
- }
- /*
- string Div(string a,string b)
- {//除法,循环减去除数
- string result = a;
- string s = "0";
- int num = 0;
- for(;result != "0" && Great(result,b);)
- {
- result = Sub(result,b);
- s = Add(s,"1");
- }
- return "商: "+s+" 余: "+result;
- }
- */
- string Div(string a,string b)
- {//除法通过模拟人工手算...
- string s = "0";
- if(b == "0")
- {
- return "Error";
- }
- for(; a != "0" && Great(a,b);)
- {
- int b_size = b.size();
- int a_size = a.size();
- int a_b = a_size - b_size;//被除数 与 除数的位差
- string s_temp = "1";
- string a_temp(a,0,b_size);
- for(; !Great(a_temp,b);)
- {//需要被除数的前几位, 11 / 2, 则需 被除数的前2位
- a_b--;
- a_temp.push_back(a[b_size++]);
- }
- for(; Great(a_temp,Mul(b,s_temp));)
- {//如11 / 2 则 s_temp = 6 后退出。
- s_temp = Add(s_temp,"1");
- }
- s_temp = Sub(s_temp,"1");
- for(; a_b > 0; a_b--)
- {//补0
- s_temp = s_temp + "0";
- }
- a = Sub(a,Mul(b,s_temp));//剩余未除的数
- s = Add(s,s_temp);//商的结果
- }
- return "商: "+ s +" 余: "+a;
- }