node python 速度_Java,Node,Python 运行速度比较
首先聲明我并不是想證明某一個語言比另外一個好,因為每一個語言都是圖靈完備的
撰寫該博客的起因是看到朋友轉發了一條這樣的微博:
為了保證公平,三種語言的代碼邏輯都是一致的,并且都是在同一個電腦上運行的
話不多說,直接上代碼
Python 代碼(3.6.5)
import time
# 判斷是否為質數
def isPrime(num):
for i in range(2, (int)(num / 2)):
if num % i == 0:
return False
return True
# 獲取3出現的次數
def getThreeNumbers(num):
res = 0
for i in range(3, num, 2):
n = i
while(n > 0):
if n % 10 == 3:
res = res + 1
n = int(n / 10)
print ('3出現的次數:' + str(res))
# 獲取微信ID
def getWechatID(num):
for i in range(2, int(num / 2)):
if num % i != 0:
continue
div = int(num / i)
if !isPrime(i) or !isPrime(div):
continue
res = ''
if div > i:
res = res + str(div) + str(i)
else:
res = res + str(i) + str(div)
getThreeNumbers(int(res))
print('微信ID:NY' + res)
return
start = time.time()
getWechatID(707829217)
end = time.time()
print ('Time cost:' + str((end - start)))
Node(JavaScript)代碼(10.15.3)
console.time('Time cost')
//判斷一個數是否為質數
const isPrime = num => {
for(let i = 2; i < Math.floor(num / 2); i++){
if(num % i == 0) return false
}
return true
};
//得到3出現的次數
const getThreeNumbers = num => {
let res = 0
for(let i = 3; i <= num; i+=2){
let n = i
while(n > 0){
if(n % 10 == 3) res++
n = Math.floor(n / 10)
}
}
return res
};
//得到微信ID
const getWechatID = num => {
for(let i = 2; i < Math.floor(num / 2); i++){
if(num % i != 0) continue
let div = num / i
if(isPrime(i) && isPrime(div)){
let res = div > i ? `${div}${i}` : `${i}${div}`
console.log(`3的次數:${getThreeNumbers(res)}`);
return res
}
}
}
console.log(`微信ID:NY${getWechatID(707829217)}`);
console.timeEnd('Time cost')
Java 代碼(1.8.0_201)
public class Test {
public static void main(String[] args) {
long startTime=System.currentTimeMillis();
getWechatID(707829217);
long endTime=System.currentTimeMillis();
System.out.println("Time cost: " + (endTime - startTime) + "ms");
}
//判斷是否是質數
public static boolean isPrime(int num){
for(int i = 2; i < num / 2; i++){
if(num % 2 == 0) return false;
}
return true;
}
//獲取微信ID
public static void getWechatID(int num){
for(int i = 2; i < num / 2; i++){
if(num % i != 0) continue;
int div = num / i;
if(!isPrime(div) || !isPrime(i)) continue;
String res = "";
if(div > i){
res = res + div + i;
}else{
res = res + i + div;
}
getThreeNumbers(Integer.parseInt(res));
System.out.println("微信ID:NY" + res);
return;
}
}
//獲取3出現的次數
public static void getThreeNumbers(int num){
int res = 0;
for(int i = 3; i <= num; i += 2){
int n = i;
while(n > 0){
if(n % 10 == 3){
res ++;
}
n = n / 10;
}
}
System.out.println("3出現的次數:" + res);
}
}
運行結果
Python
注意一下,這里的單位是秒不是毫秒(ms),轉化成毫秒就是 1926298ms
Node
Java
分析
且不談優化,我知道我的解法肯定有待優化,至少這里三種代碼的邏輯是一致的
從結果數字來看,python 的確是慢了很多,Java 的確是快很多
Java:15277ms
Node:70327ms
Python:1926298ms
下面分析原因:
算法復雜度
由于用到了雙層循環,所以算法的時間復雜度是
O(n^2)$$
其實準確的說,這里的時間復雜度是
$$O(\frac{1}{2} * \frac{1}{2} * n^2 + \frac{1}{2} * n * log_{10}n)$$
只保留最高次項,同時忽略最高項的系數得到
$$O(n^2)
代碼編寫時間
在這里具體的編寫代碼時間不好測量,因為我對每個語言的熟練程度不一樣
但是 Java 代碼的行數最多,至少能說明鍵盤敲得次數更多
語言特性
強弱類型(動靜態類型)
Java 是強類型語言(靜態類型)
而 Python,Node(JavaScript)是弱類型語言(動態類型)
這意味著 Python 跟 Node 需要在運行時作類型檢查以及轉換,所以速度自然會受影響
語言類型
Java 是編譯型語言
Node(JavaScript)是混合型語言(為啥是混合型,我也是 Google 了一下,感興趣的自己 Google)
Python 是解釋型語言
Python 需要對代碼進行讀取,詞法分析,解析,編譯,解釋和運行
Node 第一次也需要如上步驟,但是執行相同的邏輯時,將會跳過讀取,詞法分析,解析,編譯,解釋,直接運行
Java 則是先編譯,然后直接運行
結論
語言本身并無優劣之分
當需要重復計算時,Python 的速度的確慢很多,Java 的確有優勢
選擇哪一種語言取決于你想用它做什么以及你的成本是多少,包括硬件成本,時間成本,只有根據你的具體需求才能選擇對的語言去開發,不能空談效率
算法優化
想了想還是繼續優化一下算法吧,之前給出的復雜度計算有誤,已經改正
循環邊界判斷優化
感謝(@kafuly)給出的建議
將 isPrime() 以及 getWechatID() 函數中的循環邊界都改成 i <= num / 3,這里三種語言代碼稍稍有點區別:
Java 直接修改即可
i <= num / 3
Node 需要調用 Math.floor()
i <= Math.floor(num / 3)
Python 需要調用 int()函數
i <= int(num / 3)
優化完畢后,復雜度是:
O(\frac{1}{3} * \frac{1}{3} * n^2 + n*log_{10}n)
進一步思考
這里我們先計算一下復雜度里第一項與第二項的大小:
第一項:
\frac{1}{3} * \frac{1}{3} * n^2
這里 n 的最大值是 8171
所以計算次數是
8171 * 8171 * 1/9 \approx 7418360
第二項:
n * log_{10}n
這里的 n 最大值是 866278171,所以計算次數為:
866278171 * log_{10}866278171 \approx 7742497480
這里可以看到第二項的計算次數占了很大的比重
繼續優化,下面分情形探討一下 n 以內的奇數序列中 3 出現的個數
n 為 10 的整數次冪數時
n=10
f(10) = 1
n = 100
3, 13, 23, 33, 43, 53, 63, 73, 83, 93 總共 10 次
30, 31, 32, 33, 34, 35, 36, 37, 38, 39 出現 10 次
只保留奇數序列,且 33 重復計算一次,所以結果為:
f(100) = 10*1+\frac{10}{2}=15
n = 1000
10 * 15 + \frac{100}{2} = 200
可以推出:
f(n) = f(10n-1)*10 + 10n-1/2
n = 10 的整數次冪的整數倍數時
n = 300
3 * f(100) = 3 * 15 = 45
n = 700
7 * f(100) + 100 / 2 = 7 * 15 + 50 = 155
推出:
當系數 <=3 時
f(a*10b) = a*f(10b)
當系數 >3 時
f(a*10b) = a*f(10b) + 10n-1/2
n 為一般情況時
n = 1764
f(1764) = f(1000) + 7*f(100) + 10*f(10)/2 + 6*f(10) + 10/2 + f(4)
f(1000) = 10*f(100) + 100/2
f(100) = 10*f(10) + 10 / 2
f(10) = 1
f(4) = 1
=> f(100) = 15
=>f(1000) = 200
=>f(1764) = 200 + 7*15 + 100/2 + 6*1 + 5 + 1 = 367
優化之后的代碼
優化之后,我們的 getThreeNumbers() 方法看上去就是這樣的:
Java
//獲取3出現的次數
public static int getThreeNumbers(int num){
if(num < 3){
return 0;
}
if(num >= 3 && num <= 10){
return 1;
}
//得到num比10的多少次方大(或相等)
int pow = (int)Math.log10(num);
int afterPow = (int)Math.pow(10, pow);
//得到系數
int times = num / afterPow;
//得到剩余部分
int remindPart = num % (times * afterPow);
if(times > 3){
return times*f(pow) + afterPow/2 + getThreeNumbers(remindPart);
}
return times*f(pow) + getThreeNumbers(remindPart);
}
//獲得10的整數次冪的結果
public static int f(int pow){
if(pow == 1){
return 1;
}
return 10*f(pow-1) + (int)Math.pow(10, pow - 1)/2;
}
Node 代碼
//得到3出現的次數
const getThreeNumbers = num => {
if(num < 3){
return 0;
}
if(num >= 3 && num <= 10){
return 1;
}
let pow = Math.floor(Math.log10(num))
let afterPow = Math.pow(10, pow)
let times = Math.floor(num / afterPow)
let remindPart = num % (times * afterPow)
if(times > 3){
return times*f(pow) + afterPow/2 + getThreeNumbers(remindPart)
}
return times*f(pow) + getThreeNumbers(remindPart)
};
//獲得10的整數次冪的結果
const f = pow => {
if(pow == 1){
return 1
}
return 10 * f(pow - 1) + Math.pow(10, pow-1)/2
};
Python
# 獲取3出現的次數
def getThreeNumbers(num):
if num < 3:
return 0
if num >=3 and num <= 10:
return 1
pow = int(math.log10(num))
afterPow = int(math.pow(10, pow))
times = int(num / afterPow)
remindPart = num % afterPow
if times > 3:
return times*f(pow) + afterPow/2 + getThreeNumbers(remindPart)
return times*f(pow) + getThreeNumbers(remindPart)
# 獲得10的整數次冪的結果
def f(pow):
if pow == 1:
return 1
return 10*f(pow - 1) + math.pow(10, pow-1)/2
優化結果
Java
1ms
Node
11.6ms
Python
11.9ms
再次分析
可以看到,Java 的速度優勢已經體現不出來多少了,10ms 的差距是感受不到的
反而這個時候 Java 的編譯速度 + 代碼撰寫速度比較長了
再看復雜度
現在的總復雜度其實還是:
O(n^2)
第一項的計算次數還是
8171 * 8171 * 1/9 \approx 7418360
第二項的計算次數
因為用了遞歸,其實這里還可以優化,可以將遞歸改成非遞歸,這里就不繼續寫了
f(n)=log_{10}n + log_{10}(n-1) + ... + log_{10}1
將 n = 866278171 代入得:
f(n)\approx36
到這里,解題 + 優化的過程全部結束
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的node python 速度_Java,Node,Python 运行速度比较的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python中prettytable模块
- 下一篇: python简单爬虫程序分析_[Pyth