2 回答

TA貢獻1807條經驗 獲得超9個贊
您可以使用腳本的第一部分來做到這一點!
代碼:
from math import *
import time
MAX = 40000000
t = time.time()
# factors[i] = all the prime factors of i
factors = {}
# Running over all the numbers smaller than sqrt(MAX) since they can be the factors of MAX
for i in range(2, int(sqrt(MAX) + 1)):
# If this number has already been factored - it is not prime
if i not in factors:
# Find all the future numbers that this number will factor
for j in range(i * 2, MAX, i):
if j not in factors:
factors[j] = [i]
else:
factors[j].append(i)
print(time.time() - t)
for i in range(3, 15):
if i not in factors:
print(f"{i} is prime")
else:
print(f"{i}: {factors[i]}")
結果:
3: 是質數
4: [2]
5: 是質數
6: [2, 3]
7: 是質數
8: [2]
9: [3]
10: [2, 5]
11: 是質數
12: [2, 3]
13: 是質數
14: [2, 7]
解釋:
正如評論中提到的,它是對埃拉托色尼篩法算法的修改。
對于每個數字,我們找到它可以在未來因式分解的所有數字。
如果該數字未出現在結果字典中,則它是素數,因為沒有數字將其分解。我們使用字典而不是列表,因此根本不需要保存質數——這對內存更友好但也有點慢。
時間:
根據MAX = 40000000with time.time(): 110.14351892471313seconds 的簡單檢查。
對于MAX = 1000000:1.0785243511199951秒。
對于MAX = 200000000with time.time():1.5 小時后未完成...它已達到主循環中 6325 項中的第 111 項(這還不錯,因為循環越遠,它們變得越短)。
然而,我確實相信一個寫得很好的 C 代碼可以在半小時內完成(如果你愿意考慮它,我可能會寫另一個答案)??梢宰龅母鄡灮鞘褂枚嗑€程和一些像 Miller–Rabin 這樣的素數測試。當然值得一提的是,這些結果是在我的筆記本電腦上得出的,也許在 PC 或專用機器上它會運行得更快或更慢。

TA貢獻1842條經驗 獲得超13個贊
編輯:
我實際上在代碼審查中問了一個關于這個答案的問題,它有一些關于運行時的很酷的圖表!
編輯#2:
有人回答了我的問題,現在代碼經過一些修改可以在 2.5 秒內運行。
由于之前的答案寫在里面,Python所以速度很慢。下面的代碼做的是完全相同的,但在 中C++,它有一個線程每 10 秒監控一次它獲得了哪個素數。
#include <math.h>
#include <unistd.h>
#include <list>
#include <vector>
#include <ctime>
#include <thread>
#include <iostream>
#include <atomic>
#ifndef MAX
#define MAX 200000000
#define TIME 10
#endif
std::atomic<bool> exit_thread_flag{false};
void timer(int *i_ptr) {
for (int i = 1; !exit_thread_flag; i++) {
sleep(TIME);
if (exit_thread_flag) {
break;
}
std::cout << "i = " << *i_ptr << std::endl;
std::cout << "Time elapsed since start: "
<< i * TIME
<< " Seconds" << std::endl;
}
}
int main(int argc, char const *argv[])
{
int i, upper_bound, j;
std::time_t start_time;
std::thread timer_thread;
std::vector< std::list< int > > factors;
std::cout << "Initiallizating" << std::endl;
start_time = std::time(nullptr);
timer_thread = std::thread(timer, &i);
factors.resize(MAX);
std::cout << "Initiallization took "
<< std::time(nullptr) - start_time
<< " Seconds" << std::endl;
std::cout << "Starting calculation" << std::endl;
start_time = std::time(nullptr);
upper_bound = sqrt(MAX) + 1;
for (i = 2; i < upper_bound; ++i)
{
if (factors[i].empty())
{
for (j = i * 2; j < MAX; j += i)
{
factors[j].push_back(i);
}
}
}
std::cout << "Calculation took "
<< std::time(nullptr) - start_time
<< " Seconds" << std::endl;
// Closing timer thread
exit_thread_flag = true;
std::cout << "Validating results" << std::endl;
for (i = 2; i < 20; ++i)
{
std::cout << i << ": ";
if (factors[i].empty()) {
std::cout << "Is prime";
} else {
for (int v : factors[i]) {
std::cout << v << ", ";
}
}
std::cout << std::endl;
}
timer_thread.join();
return 0;
}
它需要用以下行編譯:
g++ main.cpp -std=c++0x -pthread
如果您不想將整個代碼轉換為 C++,您可以使用 Python 中的子進程庫。
時間:
好吧,我盡了最大努力,但它仍然運行了一個多小時……它6619在 1.386111 小時(4990 秒)內達到了第 855 個素數(好多了?。?。所以這是一個進步,但還有一段路要走?。]有另一個線程可能會更快)
添加回答
舉報