Stanford Algorithms (a): Multiply by large number (C + +)
Just not in the Chinese university Mooc attended the course of Chen teacher 数据结构
, Harvest very big. Feel the strike, also put the algorithm part also to a school, on the Coursera registered a Stanford University algorithm class, the amount of the course is very heavy, estimated to learn a semester, slowly learn, steady.
The course recommended a lot of books, I found a book, the title is called Algorithms
, the author is Professor S.dasgupta, a simple look at a bit, think write very good, let this book as a textbook.
Or that sentence, your fine is not expensive, a study in depth, the harvest will be very large, in short:
Don't be a impetuous person.
The first lesson is a very interesting question: multiply two numbers.
Some people may ask, this is difficult, the program directly can calculate, but the problem is two 64 numbers multiplied, this is interesting.
The algorithm, which calculates the multiplication of two numbers, has been introduced in the video, that is, the thought of splitting, the invocation of recursion, the original O (n^2) problem into O (LOGN), the efficiency is not improved a lot.
I went to the internet, found that this is a very famous, called large number multiplication algorithm problem, referring to some articles, but the feeling is not written in detail.
I implemented it in C + +. Let's take a look at the idea:
1. Too many numbers, int definitely not, use string
2. Specific algorithms have been made, the difficulty of implementation is to achieve the addition, subtraction, and multiplication between two string numbers.
The functions to be used are probably these:
string multiply(string x, string y);string simplyMultiply(string x, string y);int string2int(string x);string int2string(int x);string add(string x, string y);string Minus(string x, string y);string addZero(string x, int zeroNum);string addPreZero(string x, int zeroNum);string reverseString(string s);int Max(int x, int y);
Three of these functions are relatively simple:
int Max(int x, int y){ /* * Description: find max number * Input: Two integers * Output: Return max between x and y */ return x > y ? x : y;}int string2int(string x){ /* * Description: Change string to int * Input: A string * Output: Return a integer represents origin string */ int n = x.length(); int s = 0; for(int i = 0; i < n; ++i){ s = 10 * s + x[i] - ‘0‘; } return s;}string int2string(int x){ /* * Description: Change int to string * Input: An integers * Output: Return a string represents origin integers */ string result; stringstream stream; stream << x; stream >> result; return result;}
With the help of the StringStream, it is easy to implement conversions between types, which of course involve string.
Two string of the addition and subtraction, consider the usual way of hand calculation, is the tail alignment, so the implementation of the program, first turn them upside down, into the head alignment, convenient calculation.
string simplyMultiply(string x, string y){ /* * Description: multiply two string, whose length = 1 * Input: Two string * Output: Return product */ if(x.empty() | y.empty()){ return int2string(0); }else{ int result = string2int(x) * string2int(y); return int2string(result); }}string reverseString(string s){ /* * Description: Reverse the string * Input: A string * Output: Return a reversed string */ string result; for(auto temp = s.end() - 1; temp >= s.begin(); --temp){ result.push_back(*temp); } return result;}
There are two additional operations, which is to add 0 before and after the string, 0 is added in order to let two strings of equal number of bits, because this algorithm processing is two equal length string, so to complement the bit, otherwise it will be a problem, followed by 0, is to use the case of multiplying with 10^n.
string addZero(string x, int zeroNum){ /* * Description: Add zero between a string, simulate x * 10^n * Input: A string, a integer represents zero‘s number after it * Output: Return a string, which is added n‘s 0 */ string temp(zeroNum, ‘0‘); x.append(temp); return x;}string addPreZero(string x, int zeroNum){ /* * Description: Add zero before a string to fill in empty place * Input: A string, a integer represents zero‘s number * Output: Return a string, which is added n‘s 0 before it */ string temp(zeroNum, ‘0‘); temp.append(x); return temp;}
The best thing to do is to simulate two string-plus-minus operations. With the first few methods to pave the way, it is not difficult to achieve. Among them,
The add operation mimics the 10-in-1
The minus operation mimics the lack of a high
The details must be noted, otherwise the bug is difficult to see.
String Add (String x, string y) {/* * Description:add-String * input:two strings * Output:return thei R sum */int i, more = 0, tempsum = 0; x = reversestring (x); y = reversestring (y); int maxSize = Max (X.size (), y.size ()); string s (maxSize + 1, ' 0 '); for (i = 0; i < x.size () && i < Y.size (), ++i) {tempsum = x[i]-' 0 ' + y[i]-' 0 ' + more; S[i] = tempsum% 10 + ' 0 '; more = TEMPSUM/10; } if (I! = Y.size ()) {for (; I < y.size (); ++i) {tempsum = y[i]-' 0 ' + more; S[i] = tempsum% 10 + ' 0 '; more = TEMPSUM/10; }}else if (i! = X.size ()) {for (; I < x.size (); ++i) {tempsum = x[i]-' 0 ' + more; S[i] = tempsum% 10 + ' 0 '; more = TEMPSUM/10; }} if (more! = 0) {S[i] + = more; }else{S.pop_back (); } s = reversestring (s); return s;} string minus (string x, string y) {/* * DESCRIption:minus between Strings * input:two strings * Output:return their difference */int i; x = reversestring (x); y = reversestring (y); String s (x.size (), ' 0 '); for (i = 0; i < y.size (); ++i) {if (X[i] < Y[i]) {X[i] + = 10; X[i + 1]-= 1; } S[i] = X[i]-y[i] + ' 0 '; } for (; I < x.size (); ++i) {s[i] = X[i]; } for (i = X.size ()-1; i > 0; i) {if (s[i] = = ' 0 ') {s.pop_back (); }else{break; }} s = reversestring (s); return s;}
With this in front, multi () is very simple to write, and it is important to note that the number of digits is odd.
string multiply(string x, string y){ /*Description: Multiply between two strings *Input: Two strings, represents two positive integers *Output: Return product of x and y */ int xSize = x.length(); int ySize = y.length(); int n = Max(xSize, ySize); if(n == xSize){ y = addPreZero(y, n - ySize); }else{ x = addPreZero(x, n - xSize); } if(n == 1){ return simplyMultiply(x, y); } string xLeft = x.substr(0, n / 2); string xRight = x.substr(n / 2); string yLeft = y.substr(0, n / 2); string yRight = y.substr(n / 2); string p1 = multiply(xLeft, yLeft); string p2 = multiply(xRight, yRight); string p3 = multiply(add(xLeft, xRight), add(yLeft, yRight)); string p4 = Minus(Minus(p3, p1), p2); string result = add(add(addZero(p1, 2 * (n - n / 2)), addZero(p4, n - n / 2)), p2); return result;}
Now, you can multiply it, and two 64-digit numbers.
Here's the code: multiply by large number
Summary: Previously rarely considered how the two number is multiplied, written in the program, maybe just a sign, do not know the middle, there have been so many stories. Now we often face, not the lack of tools, but the tool package is too good, programmers like to be lazy, but to get real improvement, the box, is to open it sooner or later. I think this is the data structure and algorithm class, to my very important thing, this bottom-up thinking habits, very important.
Stanford Algorithms (a): Multiply by large number (C + +)