簡體   English   中英

Python與PHP的速度

[英]Python vs PHP speed

我想解決Project Euler (BTW,問題25)中的問題,我在Python中找到了一個解決方案:

fibonacci = 1
old1 = 0
old2 = 1
limit = 1000

i = 1

while len(str(fibonacci)) < limit:
    fibonacci = old1 + old2
    old1 = old2
    old2 = fibonacci
    i = i + 1

print(i)

計算需要1.5秒。

我在PHP中實現了相同的,這是代碼:

$fibonacci = 1;
$old1 = 0;
$old2 = 1;
$limit = 1000;

$i = 1;

while (strlen((string)$fibonacci) < $limit){
    $fibonacci = $old1 + $old2;
    $old1 = $old2;
    $old2 = $fibonacci;
    $i = $i + 1;
}
print($i);

花了30多分鍾,還在計算......

我知道Python被認為比PHP更快,但它仍然不應該是那么大的差異。 如果有辦法,如何改進我的PHP代碼以更快地獲得結果?

編輯:

我根據下面的評論編輯這篇文章,所以首先我的解決方案不起作用。 放一個解決方案可以代替舊的:

while (strlen(number_format($fibonacci, 0, '', '')) < $limit){ ... }

但這又是一個很大的速度問題。

所以最終的解決方案是使用BCMath

$fibonacci = '1';
$old1 = '0';
$old2 = '1';
$limit = 1000;

$i = 1;

while (strlen($fibonacci) < $limit){

    $fibonacci = bcadd($old1, $old2);
    $old1 = $old2;
    $old2 = $fibonacci;
    $i = $i + 1;
}
echo $fibonacci . "<br />";
print($i);

因此,您可以以與Python中的Python相同的速度獲得結果。

當然,PHP正在進入無限循環。 如果沒有什么不對的話,就沒有辦法花那么長時間......

我不認為使用strlen計算這些數字的數字將在PHP中起作用。 PHP以科學計數法處理數字,精度低於Python。

我在PHP中添加了調試echo語句,為每一步打印出$ fibonacci和$ i。

典型的Python行看起來像

fib is 7540113804746346429
i is 92

在PHP中,那是

fib is 7.54011380475E+18
i is 92

要在PHP中實現這一點,您可能需要使用更高精度的數學庫。

查看http://www.php.net/manual/en/book.bc.php - 您可以使用bcadd函數來完成添加,它將像在Python中一樣工作。

這不是速度問題,它是終止條件下的邏輯問題。

它可能不會完成。 當您將$ fibonacci的當前值轉換為while測試中的字符串時,當您將其轉換為字符串時,它將轉換為科學格式並截斷為一組有限的小數位(取決於您的精度設置)。 該位數將遠遠小於1000,因此永遠不會滿足while終止條件。

問題是,你正在處理大數字。 您應該使用BC Math Functions( php.net/bc )。 所以你的代碼可以是:

$fibonacci = "1";
$old1 = "0";
$old2 = "1";
$limit = 1000;

$i = 1;

while (strlen($fibonacci) < $limit){
    $fibonacci = bcadd($old1, $old2);
    $old1 = $old2;
    $old2 = $fibonacci;
    $i = $i + 1;
}
print($i);

我已經嘗試過,它需要大約0.095秒。

由於問題似乎是轉換為字符串,所以這是一種更快的方法,不需要它。 這基本上與您發布的算法相同(所以我不會覺得很難顯示給您),但演示了如何使用除法來測試整數的長度,而不是將其轉換為字符串。

def fibonacci_digits(limit):
    limit = 10**limit
    fib = 1
    old1 = 0
    old2 = 1

    i = 1
    size = 1
    while size < limit:
        fib = old1 + old2
        if not size//fib:  # // is pythons integer division operator, not a comment
            size *= 10
        old1 = old2
        old2 = fib
        i += 1

    return i

print fibonacci_digits(1000)

轉換為字符串很慢,幾乎不是正確的事情。 這是時間結果:

$ python -mtimeit -s'import fib' 'fib.fibonacci_digits(1000)'
10 loops, best of 3: 30.2 msec per loop

$ python -mtimeit -s'import fib' 'fib.fibonacci_digits2(1000)'
10 loops, best of 3: 1.41 sec per loop

許多項目歐拉問題將不得不處理大數字。 PHP將使您的大數字看起來像2.579234678963E+12 ,這是數字的指數表示......顯然很難使用。 因此,對於大多數問題,最好使用BCMath函數 這將保持您的號碼不變,即使它是一個巨大的數字。

注意使用echo bcmul(500,500); 永遠不會像echo 500*500那么快。 並且,BCMath函數返回值始終是字符串。

要解決您的問題,請使用相應的BCMath函數替換所有算術運算。

我優化了一些Python代碼。 使用len(str())來檢查位數非常慢。 由math.log10替換,可以更快地運行程序

Fibonacci序列中包含1000個數字的第一項是:4782以0.008573秒計算

import time
from math import log10


def digits(n): # Return the number of digits for n>=1
    return int(log10(n))+1

fibonacci = 1L # Thanks to Python to handle very big numbers
old1 = 0
old2 = 1
limit = 1000

i = 1


start = time.time() #Start timer for bench
while digits(fibonacci) < limit:
    fibonacci = old1 + old2
    old1 = old2
    old2 = fibonacci
    i +=  1



print "The first term in the Fibonacci sequence to contain %s digits is : %s" % (str(limit), str(i))

print "Calculated in %3.6f seconds" %  (time.time() - start)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM