簡體   English   中英

Java System.currentTimeMillis() 方法的正確用法?

[英]Correct usage of Java System.currentTimeMillis() method?

我正在比較 Java 中計算迭代和遞歸階乘過程的時間。我正在嘗試使用System.currentTimeMillis方法來比較每種算法計算所需的時間,但我似乎無法計算差異。 我不確定使用此方法的正確方法是什么,但這里的任何事件都是我試圖在我的代碼中實現的:

// ... more code above

System.out.print("Please enter an integer: ");
int integer = readInt();
System.out.println();

// demonstrate recursive factorial and calculate
// how long it took to complete the algorithm
long time1 = System.currentTimeMillis();
int fact1 = factRecursive(integer);
long time2 = System.currentTimeMillis();
System.out.format("Result of recursive factorial %s is %d\n", integer, fact1);
System.out.format("Algorithm took %d milliseconds\n\n", (time2 - time1));

// ... more code below

這是 output:

Please enter an integer: 25

Result of recursive factorial 25 is 2076180480
Algorithm took 0 milliseconds

Result of iterative factorial 25 is 2076180480
Algorithm took 0 milliseconds

顯然,我一定是在這里做錯了什么,因為兩種情況下計算階乘的預期時間不應該為零。

編輯:這是我的階乘解決方案,如果有人感興趣的話(不是特別獨特,但無論如何它們都在這里):

// factRecursive uses a recursive algorithm for 
// caluclating factorials.
public static long factRecursive(long n)
{
    return n = (n == 1)? 1 : n * factRecursive(n - 1);
}

// factIterative uses an iterative algorithm for
// calculating factorials.
public static long factIterative(long n)
{
    long product = 1;

    if(n == 1) return n;

    for(int i = 1; i <= n; ++i)
        product *= i;

    return product;
}

並且是一些 output。令人驚訝的是,遞歸版本運行良好。 直到 39 歲左右,迭代版本才開始明顯好轉。

Please enter an integer: 39

Result of recursive factorial 39 is 2304077777655037952
Algorithm took 5828 nanoseconds

Result of iterative factorial 39 is 2304077777655037952
Algorithm took 5504 nanoseconds

System.currentTimeMillis()的分辨率可能會有所不同,具體取決於您的系統; 看來您的算法太快了,無法使用此計時器進行測量。

請改用System.nanoTime() 它的准確性也取決於系統,但至少它能夠進行高分辨率時間測量。

即時編譯會對性能產生很大影響,但大多數虛擬機都需要在重新編譯之前多次調用某個方法。 這使得很難從這種微基准測試中獲得准確的結果。

對於 n = 25,一個寫得很好的階乘 function 應該執行得非常快,所以讓它在大約 0 毫秒內運行並不奇怪。 您有以下三種選擇:

  1. 使用更大的 n。 這將導致階乘 function 花費更長的時間,並給你一些東西來衡量。
  2. 使用System.nanoTime以近似納秒而不是毫秒來測量時間。
  3. 我建議同時執行 1 和 2。

正如其他回答者指出的那樣,您確實是從開始減去結束,這是倒退的。 顯然,你也應該解決這個問題。 但這種變化只會影響結果的符號,不會影響絕對值。


編輯:只是為了看看找到 25 的階乘有多快,我寫了這個 Python 實現

>>> def fact(n):
...     def _fact(n, acc):
...             if n == 1:
...                     return acc
...             return _fact(n - 1, n * acc)
...     if n < 0:
...             return 0 # Or raise an exception
...     if n < 2:
...             return 1
...     return _fact(n, 1)
... 
>>> fact(25)
15511210043330985984000000L
>>> import timeit
>>> t = timeit.Timer("fact(25)", "from __main__ import fact")
>>> print t.timeit()
6.2074379921

盡管 Python 是一種沒有尾調用優化的解釋型動態類型語言,但使用累加器的簡單遞歸解決方案可以在我的機器上在 6.2 秒內找到一百萬次fact(25) 所以平均執行時間是 6.2 微秒。 沒有機會在具有毫秒時鍾精度的單次運行中測量迭代和遞歸解決方案之間的實質性差異。

你需要做的(完成時間 - 開始時間),你已經落后了。

試試這個:

System.out.format("Algorithm took %d milliseconds\n\n", (time2 - time1));

很常見的錯誤。 您應該從 time2 中減去 time1。

如果您明智地命名您的變量將會有所幫助 - 例如startTimeendTime這樣您就會知道或至少發現您必須做endTime - startTime as endTime > startTime

看起來您的快速遞歸畢竟可能不會進行如此繁重的處理。

請改用System.nanoTime() 它返回納秒

http://docs.oracle.com/javase/7/docs/api/java/lang/System.html

nanoTime() 返回正在運行的 Java 虛擬機的高分辨率時間源的當前值,以納秒為單位。


另一種測試方法是將階乘迭代 1000 次。 然后將時差除以 1000.00(雙倍)

要獲得有意義的計時結果,您需要重復並忽略調用方法的前 10,000 次(因此代碼已編譯),並且您需要再運行 2-10 秒(重復)。

暫無
暫無

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

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