2009-06-23 99 views
0

我有一段糟糕的時間讓自己相信我在這裏所做的是一個好主意。具體的部分,我覺得反感的是:在PHP中使用microtime和浮點數不精確的數字

return ((float)($now+$sec).'.'.$mic); 

爲了保持浮點精度,我被迫要麼依傍BC或GMP庫(均未始終可用)。在這種情況下,我使用串連接干擾了數字。

<?php 

// return the current time, with microseconds 
function tick() { 
    list($sec, $mic, $now) = sscanf(microtime(), "%d.%d %d"); 
    return ((float)($now+$sec).'.'.$mic); 
} 

// compare the two given times and return the difference 
function elapsed($start, $end) { 
    $diff = $end-$start; 

    // the difference was negligible 
    if($diff < 0.0001) 
     return 0.0; 

    return $diff; 
} 

// get our start time 
$start = tick(); 

// sleep for 2 seconds (should be ever slightly more than '2' when measured) 
sleep(2); 

// get our end time 
$end = tick(); 

$elapsed = elapsed($start, $end); 

// should produce output similar to: float(2.00113797188) 
var_dump($elapsed); 

?> 

如果我嘗試添加兩個數字像(代表時間戳)和0.0987654321(代表微秒),使用加法運算符(+)我總是用123456789.099結束。即使將整數轉換爲浮點數,結果也是一樣的。

是否有解決這個問題的方法是1)不是破解和2)不涉及字符串連接?爲了獲得精確的微秒分辨率時間戳,我不應該回頭看這種亂碼。

編輯:正如S. Gehrig所解釋的,PHP中的浮點數有時可能會有點棘手顯示。 PHP配置中指示的「精度」與顯示有關。實際值並不像我想象的那樣圓整。一個簡單得多的解決方案上面的代碼看起來像這樣:

// return the current time, with microseconds 
function tick() { 
    return microtime(true); 
} 

// compare the two given times and return the difference 
function elapsed($start, $end) { 
    return $end-$start; 
} 

// get our start time 
$start = tick(); 

// sleep for 2 seconds (should be ever slightly more than '2' when measured) 
sleep(2); 

// get our end time 
$end = tick(); 

$elapsed = elapsed($start, $end); 

// should produce output similar to: float(2.00113797188) 
var_dump($elapsed); 

如果你要檢查$開始$從另一箇中減去一個之前結束,它可能會出現,他們舍入到百分之一位置。不是這種情況。在顯示有限的情況下,似乎任意的算術精度被保留。

回答

2

爲什麼不使用microtime(true),它僅僅返回微秒時間戳爲float?在PHP 5.0.0中添加了參數[bool] $get_as_float

關於對精度 「損失」 的評論:

$start = microtime(true); 
$end = microtime(true); 
echo $end - $start; 
// prints 7.1526861190796 

microtime(true)不限於小數點後2位。海報遇到的是配置設置precision的影響,它控制輸出浮點變量時將打印多少個小數位。 這與內部精度microtime(true)的用途無關。您可以隨時使用number_format()(s)printf()將輸出格式化爲您喜歡的精度。

+0

我會的,但精度是舍入到2個地方,似乎沒有辦法改變這一點。默認情況下,PHP的精度是12位......但這個函數並不尊重它。檢查它: php -r'echo microtime(true);' 我不知道是什麼原因導致它圓形的。 – spligak 2009-06-23 08:03:38

+0

float的12位小數的精度INCLUDES逗號前的小數 - 所以12位精度就是您所看到的。 – 2009-06-23 08:19:01

0

浮點類型固有地不精確。要麼與之共存,要麼不要使用它們。

1

首先,spligak,我看到你的代碼包含錯誤。

list($sec, $mic, $now) = sscanf(microtime(), "%d.%d %d"); 
return ((float)($now+$sec).'.'.$mic); 

如果$ mic少於六位數字,則會得到垃圾結果。請在

the case where microtime() returns "0.000009 1234567890" 

二辦公桌檢查,可以大大降低浮點錯誤如下: (警告:未經測試的代碼)

//比較兩個給定的時間和返回的區別

// get our start time 
$start = microtime(); 

// sleep for 2 seconds (should be ever slightly more than '2' when measured) 
sleep(2); 

// get our end time 
$end = microtime(); 

// work around limited precision math 
// subtract whole numbers from whole numbers and fractions from fractions 

list($start_usec, $start_sec) = explode(" ", $start); 
list($end_usec, $end_sec) = explode(" ", $end); 
$elapsed = ((float)$end_usec)-((float)$start_usec); 
$elapsed += ((float)$end_sec)-((float)$start_sec); 

// please check the output 
var_dump($elapsed); 
相關問題