我很难说服自己在这里做了什么是一个好主意。我发现令人反感的具体部分是:
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);
?>
如果我尝试添加两个数字,例如 123456789 (表示时间戳)和 0.0987654321 (表示微秒),请使用加法运算符( + )我总是以123456789.099结束。即使将整数转换为float,结果也是一样。
是否有针对此问题的解决方案,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);
如果您要先检查 $ start 或 $ end ,然后再从另一个中减去一个,则可能会显示它们已四舍五入到百分位。不是这种情况。当显示受限时,似乎保持算术的任意精度。
答案 0 :(得分:2)
为什么不使用microtime(true)
只返回微秒时间戳为float
?参数[bool] $get_as_float
已在PHP 5.0.0中添加。
关于精确度“损失”的评论:
$start = microtime(true);
$end = microtime(true);
echo $end - $start;
// prints 7.1526861190796
microtime(true)
不限于2位小数。海报遇到的是配置设置precision
的效果,它控制输出浮点变量时要打印的小数位数。 这与内部精度microtime(true)
使用无关。您始终可以使用number_format()
或(s)printf()
将输出格式化为您喜欢的精度。
答案 1 :(得分: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);
答案 2 :(得分:0)
浮点类型本质上是不精确的。要么与它一起生活,要么不使用它们。