我最近写了一个简短的算法来计算python中的快乐数字。该程序允许您选择一个上限,它将确定其下的所有快乐数字。为了进行速度比较,我决定对我知道的从python到c ++的算法进行最直接的翻译。
令人惊讶的是,c 版本的运行速度明显慢于python版本。执行时间之间的准确速度测试(用于发现前10,000个快乐数字)表明python程序平均在0.59秒内运行,而c 版本平均在8.5秒内运行。
我将这种速度差异归因于这样一个事实,即我必须为已经内置在python语言中的c ++版本的部分计算(例如,确定某个元素是否在列表/数组/向量中)编写辅助函数。 。
首先,这是造成如此荒谬的速度差异的真正原因,其次,我该如何更改c ++版本以比python版本更快地执行(我认为应该如此)。
经过速度测试的两段代码在这里:Python版本,C ++版本。谢谢您的帮助。
#include <iostream> #include <vector> #include <string> #include <ctime> #include <windows.h> using namespace std; bool inVector(int inQuestion, vector<int> known); int sum(vector<int> given); int pow(int given, int power); void calcMain(int upperBound); int main() { while(true) { int upperBound; cout << "Pick an upper bound: "; cin >> upperBound; long start, end; start = GetTickCount(); calcMain(upperBound); end = GetTickCount(); double seconds = (double)(end-start) / 1000.0; cout << seconds << " seconds." << endl << endl; } return 0; } void calcMain(int upperBound) { vector<int> known; for(int i = 0; i <= upperBound; i++) { bool next = false; int current = i; vector<int> history; while(!next) { char* buffer = new char[10]; itoa(current, buffer, 10); string digits = buffer; delete buffer; vector<int> squares; for(int j = 0; j < digits.size(); j++) { char charDigit = digits[j]; int digit = atoi(&charDigit); int square = pow(digit, 2); squares.push_back(square); } int squaresum = sum(squares); current = squaresum; if(inVector(current, history)) { next = true; if(current == 1) { known.push_back(i); //cout << i << "\t"; } } history.push_back(current); } } //cout << "\n\n"; } bool inVector(int inQuestion, vector<int> known) { for(vector<int>::iterator it = known.begin(); it != known.end(); it++) if(*it == inQuestion) return true; return false; } int sum(vector<int> given) { int sum = 0; for(vector<int>::iterator it = given.begin(); it != given.end(); it++) sum += *it; return sum; } int pow(int given, int power) { int original = given; int current = given; for(int i = 0; i < power-1; i++) current *= original; return current; }
#!/usr/bin/env python import timeit upperBound = 0 def calcMain(): known = [] for i in range(0,upperBound+1): next = False current = i history = [] while not next: digits = str(current) squares = [pow(int(digit), 2) for digit in digits] squaresum = sum(squares) current = squaresum if current in history: next = True if current == 1: known.append(i) ##print i, "\t", history.append(current) ##print "\nend" while True: upperBound = input("Pick an upper bound: ") result = timeit.Timer(calcMain).timeit(1) print result, "seconds.\n"
对于100000个元素,Python代码花费6.9秒,而C ++最初花费了37秒以上。
我对您的代码进行了一些基本的优化,并设法使C 代码比Python实现快100倍以上。现在,它可以在0.06秒内完成100000个元素。这比原始C 代码快617倍。
最重要的是在发布模式下进行所有优化。在调试模式下,这段代码实际上要慢几个数量级。
接下来,我将解释我所做的优化。
通过使用预分配的数组而不是向量,可能甚至可以进一步优化代码,但这将需要更多的工作,我将其作为练习留给读者。:P
这是优化的代码:
#include <iostream> #include <vector> #include <string> #include <ctime> #include <algorithm> #include <windows.h> using namespace std; void calcMain(int upperBound, vector<int>& known); int main() { while(true) { vector<int> results; int upperBound; cout << "Pick an upper bound: "; cin >> upperBound; long start, end; start = GetTickCount(); calcMain(upperBound, results); end = GetTickCount(); for (size_t i = 0; i < results.size(); ++i) { cout << results[i] << ", "; } cout << endl; double seconds = (double)(end-start) / 1000.0; cout << seconds << " seconds." << endl << endl; } return 0; } void calcMain(int upperBound, vector<int>& known) { vector<int> history; for(int i = 0; i <= upperBound; i++) { int current = i; history.clear(); while(true) { int temp = current; int sum = 0; while (temp > 0) { sum += (temp % 10) * (temp % 10); temp /= 10; } current = sum; if(find(history.begin(), history.end(), current) != history.end()) { if(current == 1) { known.push_back(i); } break; } history.push_back(current); } } }