繁体   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