2009-06-28 100 views
1

是否有表格顯示在PHP中執行給定函數需要多少「工作量」?我不是一個綜合專業,所以我也許沒有正式的背景知道「哦,是的,字符串需要更長的時間來處理,而不是整數」或類似的東西。程序中的所有步驟/行是否都是平等的?我甚至不知道從哪裏開始研究。PHP函數效率

我目前正在做一些項目歐拉問題,我很確定我的答案會起作用,但是我在一分鐘內根據我的請求計時了我的本地Apache服務器(並且PE已經表示所有問題都可以解決< 1分鐘)。我不知道如何/從哪裏開始優化,所以瞭解更多關於PHP以及它如何使用內存將是有用的。對於它的價值,這是我爲question 206代碼:

<?php 
$start = time(); 
for ($i=1010374999; $i < 1421374999; $i++) { 
$a = number_format(pow($i,2),0,".",""); 
$c = preg_split('//', $a, -1, PREG_SPLIT_NO_EMPTY); 
if ($c[0]==1) { 
    if ($c[2]==2) { 
     if ($c[4]==3) { 
      if ($c[6]==4) { 
       if ($c[8]==5) { 
        if ($c[10]==6) { 
         if ($c[12]==7) { 
          if ($c[14]==8) { 
           if ($c[16]==9) { 
            if ($c[18]==0) { 
             echo $i; 
            } 
           } 
          } 
         } 
        } 
       } 
      } 
     } 
    } 
} 
} 
$end = time(); 
$elapsed = ($end-$start); 
echo "<br />The time to calculate was $elapsed seconds"; 
?> 

如果這是關於優化維基問題,只是讓我知道,我會移動。再次,沒有尋找答案,只是幫助我瞭解在編碼方面的高效性(儘管粗略的提示不會被拒絕,並且我意識到可能有更優雅的數學方法來設置問題)

+2

您最大的效率問題可能是您嘗試暴力解決方案的事實。對於這些問題,沒有任何代碼可以使暴力解決方案發揮作用。沒有太多的循環,你可以在一分鐘內完成4.11億次。而不是試圖每秒鐘擠壓更多的迭代,試着將你所做的迭代次數減少幾個數量級。 – 2009-06-28 22:34:56

+2

對於這個問題,你應該看看方形數字是如何工作的。例如mathworld.wolfram.com/SquareNumber.html。然後你會注意到,平方根的最後兩位數字只能是30或70,這已經將你的搜索空間從4.11億個數字減少到了8.220.000 – jitter 2009-06-28 23:19:42

回答

6

有這麼回事告訴你沒有這樣的表中的每個PHP多久函數需要執行,因爲執行時間會根據輸入而變化很大。

看看你的代碼在做什麼。你創建了一個將要運行411,000,000次的循環。鑑於代碼需要在不到60秒(一分鐘)內完成,爲了解決這個問題,您假設每次通過循環的行程都將少於(大約).000000145秒。這是不合理的,沒有任何數量的「正確」功能可以解決您的問題。試着用沒有你的循環中有

for ($i=1010374999; $i < 1421374999; $i++) { 

} 

除非你有機會獲得科幻小說的電腦,這可能不會在不到60秒的時間完成執行。所以你知道這種方法將永遠不會工作。

這是衆所周知的解決問題的蠻力解決方案。歐拉項目的目的是讓你從數學和編程的角度創造性地思考問題。您想要減少您需要通過該循環的次數。顯而易見的解決方案永遠不會是這裏的答案。

我不想告訴你解決方案,因爲這些東西的重點是想你的方式,併成爲一個更好的算法程序員。檢查問題,考慮限制,考慮減少需要檢查的總數。

2

採取看看執行時間爲你的代碼的好工具了XDebug:http://xdebug.org/docs/profiler

這是一個可安裝PHP擴展,可配置爲輸出的函數調用和執行時間爲您的腳本完全崩潰。使用這個,你將能夠看到你的代碼執行時間最長,並嘗試一些不同的方法。

編輯:現在,我實際上在看你的代碼,你正在運行4億+正則表達式調用!我對歐拉項目一無所知,但我很難相信這些代碼可以在商用硬件上在一分鐘之內得到解決。

+0

他的代碼不能不能解決他的問題。這就是這個歐拉項目的意義所在。數學問題,有可能寫在一分鐘內運行的求解器。 – jitter 2009-06-28 23:04:43

+0

我對它做了一些研究。正如在接受的答案中指出的那樣,這看起來像一個有趣的項目。 – 2009-06-30 16:29:13

1

preg_split可能會很慢,因爲它使用的是正則表達式。沒有更好的方法來做那條線嗎?

提示:您可以訪問字符的字符串是這樣的:

$str = 'This is a test.'; 
echo $str[0]; 
+0

這是一個很好的提示,謝謝 – 2009-06-28 22:23:10

0

首先,這裏是你的函數的一個稍微乾淨版本,調試輸出

<?php 
$start = time(); 
$min = (int)floor(sqrt(1020304050607080900)); 
$max = (int)ceil(sqrt(1929394959697989990)); 

for ($i=$min; $i < $max; $i++) { 
$c = $i * $i; 
echo $i, ' => ', $c, "\n"; 
if ($c[0]==1 
    && $c[2]==2 
     && $c[4]==3 
     && $c[6]==4 
     && $c[8]==5 
     && $c[10]==6 
     && $c[12]==7 
     && $c[14]==8 
     && $c[16]==9 
     && $c[18]==0) 
    { 
    echo $i; 
     break; 
    } 
} 
$end = time(); 
$elapsed = ($end-$start); 
echo "<br />The time to calculate was $elapsed seconds"; 

而這裏的第一個10行輸出:

1010101010 => 1020304050403020100 
1010101011 => 1020304052423222121 
1010101012 => 1020304054443424144 
1010101013 => 1020304056463626169 
1010101014 => 1020304058483828196 
1010101015 => 1020304060504030225 
1010101016 => 1020304062524232256 
1010101017 => 1020304064544434289 
1010101018 => 1020304066564636324 
1010101019 => 1020304068584838361 

也就是說,在那裏,好像它現在應該激發您的算法可能的優化。請注意,我們甚至沒有接近第六條目(1020304060504030225) - 我們有6個位置,我們需要5個位置!實際上,接下來的很多條目都是毫無價值的,直到我們回到了我們在那個位置上有5個位置的點。爲什麼要計算干預價值呢?如果我們能夠找出如何,我們應該跳到1010101060,那個數字再次變成5 ......如果我們能夠像這樣一次跳過幾十次迭代,那麼我們將節省90%以上的運行時間!

請注意,這可能根本不是一種實用的方法(事實上,我相信它不是),但這是您應該思考的方式。你可以用什麼數學技巧來減少你執行的迭代次數?