Microtime'da ve PHP kayan nokta ilavesi ile kesin olmayan numaralar

3 Cevap php

Ben ne burada yaptık iyi bir fikir kendimi ikna korkunç bir zaman yaşıyorum. Ben sakıncalı buluyorum özel bölümü:

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

Kayan nokta duyarlık korumak amacıyla, geri (her zaman kullanılabilir ikisi de) BC veya GMP kütüphaneleri üzerine düşmesine ya zorunda değilim. Bu durumda, ben dize birleştirme ile birlikte sayıları sıkışma başvurdu ettik.

<?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);

?>

Ben toplama operatörünü kullanarak, (mikrosaniye temsil eden) (damgası temsil eden) 123456789 gibi iki sayıyı eklemek için teşebbüs ve 0.0987654321 if ({[) (2]}) Ben her zaman sonuna kadar 123456789.099 ile. Float tamsayı döküm bile, sonuç aynıdır.

1) bir hack ve 2) dize birleştirme anlamına gelmez bu sorun için bir çözüm var mı? Ben mikrosaniye çözünürlükte doğru bir zaman damgası almak için bozuk kod bu tür geri düşmek zorunda olmamalıdır.

Edit: S. Gehrig olarak açıkladı, PHP kayan noktalı sayılar, zaman zaman, görüntülemek için biraz zor olabilir. PHP yapılandırmasında belirtilen "hassas" ekran ile ilgili. Düşündüğüm gibi gerçek değerleri yuvarlanır değildir. Yukarıdaki kod bir çok basit bir çözüm şöyle görünecektir:

// 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);

Eğer başka birini çıkarmadan önce $start veya $end incelemek olsaydı, onlar salise pozisyona şekilde yuvarlanır görünebilir. Bu durum böyle değil. Bu ekran sınırlı iken keyfi hassas aritmetik için korunur gibi görünüyor.

3 Cevap

Neden kullanmayın microtime(true) which simply returns a microsecond timestamp as float? Parametresi [bool] $get_as_float PHP 5.0.0 'da eklenmiştir.

Regarding the comment about the "loss" of precision:

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

{[(0)] 2} ondalık basamağa kadar sınırlı değildir. Ne afiş karşılaştığında şamandıra değişkenleri çıktısı alınırken basılacaktır kaç ondalık denetleyen yapılandırma ayarı precision etkisidir. Bu iç hassasiyet microtime(true). You can always use number_format() or (s)printf() gibi hassas çıkışı biçimlendirmek için kullandığı ile ilgisi yoktur.

Birincisi, spligak, ben senin kod bir hata içerdiğini görüyoruz.

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

$ Mikrofon az altı basamak varsa, çöp sonuçlar almak. Bir masa üzerinde kontrol etmeyin

the case where microtime() returns "0.000009 1234567890"

Second, you can greatly reduce the floating-point error as follows: (WARNING: untested code!)

/ / Verilen iki kez karşılaştırın ve farkı iade

// 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);

Kayan nokta türleri doğal olarak hatalıdır. Onunla yaşamak, ya da bunları kullanmayın ya.