我正在尝试使用填充零向右浮动(18,16),但这不起作用,因为它总是以1而不是零结束。我的猜测是因为我说错了,但我不确定如何纠正。
样品:
12.12234
必须变为12.122340000000000
且1.01
必须变为1.01000000000000
。
为了达到这个目的,我正在使用sprintf('%18.016f', $fMyFloat);
,但这总是以1而不是0结束。显然我在监督某些事情,我只是不知道是什么。非常感谢任何帮助。
答案 0 :(得分:4)
此测试代码:
$data = array(
12.12234,
1.01
);
foreach($data as $fMyFloat){
echo sprintf('%18.016f', $fMyFloat) . PHP_EOL;
}
...在我的64位计算机中打印出来:
12.1223399999999994
1.0100000000000000
您正面临众所周知的浮点精度问题。将整数从基数10转换为基数2非常简单(而且确切)但是基数10的浮点数不能总是在基数2中完全表示。这个问题不是特定于PHP,而是PHP手册中有warning :
浮点数的精度有限。虽然这取决于 在系统中,PHP通常使用IEEE 754双精度格式, 由于订单的舍入,这将产生最大的相对误差 1.11e-16。非基本算术运算可能会更大 错误,当然,必须考虑错误传播 几个操作复杂化。
此外,有理数的数字可以完全表示为 基数10中的浮点数,如0.1或0.7,没有 精确表示为基数2中的浮点数,即 内部使用,无论尾数的大小。因此,他们 没有a就无法转换成它们的内部二进制对应物 精度损失小
获得此类精确度的唯一机会是将数字操作为字符串。 PHP捆绑了两个任意精度库,可以在您需要匹配字符串时帮助您:GNU Multiple Precision和BC Math。这是bcmath的一点点破解:
$data = array(
'12.12234',
'1.01'
);
bcscale(16);
foreach($data as $fMyFloat){
echo bcdiv($fMyFloat, 1) . PHP_EOL;
}
但是,在这种情况下,您可以使用简单的字符串函数:
$data = array(
'12.12234',
'1.01'
);
foreach($data as $fMyFloat){
list($a, $b) = explode('.', $fMyFloat);
echo $a . '.' . str_pad($b, 16, 0) . PHP_EOL;
}