我在一些“humanize_bytes()”代码中遇到了一个有趣的问题。此循环表示没有所有其他逻辑的问题。当字节被截断为“人类可读”级别时,循环需要停止。它会一直迭代,直到最终值小于1024(或可指定的字节大小)。
当函数输出“1024.0 P”为1024 PB时,我开始研究这个问题。起初我以为我不小心使用了< = vs<,但经过进一步的检查,我发现发生了一些更有趣的事情。
此代码重现了该问题。我正在使用perl 5.8.8。
use strict;
my $bytesize = 1024;
my $final = 1152921504606846720;
while (1) {
printf "bytesize %%d: %d %%f: %s %s final %%d: %19d %%f: %26f\n",
$bytesize,$bytesize,
(
$bytesize == $final ? '==' :
$bytesize > $final ? '>' :
$bytesize < $final ? '<' :
'<error>'
),
$final,$final;
last if $final < $bytesize;
$final /= $bytesize;
}
printf "final = bytesize d:%d f:%s %s final d:%d f:%f\n",
$bytesize,$bytesize,
(
$bytesize == $final ? '==' :
$bytesize > $final ? '>' :
$bytesize < $final ? '<' :
'<error>'
),
$final,$final;
我收到的输出是:
bytesize %d: 1024 %f: 1024 < final %d: 1152921504606846720 %f: 1152921504606846720.000000
bytesize %d: 1024 %f: 1024 < final %d: 1125899906842623 %f: 1125899906842623.750000
bytesize %d: 1024 %f: 1024 < final %d: 1099511627775 %f: 1099511627775.999756
bytesize %d: 1024 %f: 1024 < final %d: 1073741823 %f: 1073741824.000000
bytesize %d: 1024 %f: 1024 < final %d: 1048575 %f: 1048576.000000
bytesize %d: 1024 %f: 1024 > final %d: 1023 %f: 1024.000000
final = bytesize d:1024 f:1024 > final d:1023 f:1024.000000
这里需要注意的是十进制的最终值是1023,但浮动的是1024.这怎么可能?显然,perl使用十进制表示法。
答案 0 :(得分:10)
您的原始值不是1024 PB,不到256。 (我注意到这一点,将其弹出到dc(1)并以十六进制打印:0xFFFFFFFFFFFFF00。)
因此,每次循环时你的数字都会比你预期的略有不同,最后它会略微变小。
如果你有更多的精确度,你最终会得到
1023.999999999999772626324556767940
这自然地截断为1023并且舍入为1024。
答案 1 :(得分:2)
Perl似乎将传递给%f
的值四舍五入。如果您将值包装在int($final)
中,则会得到1023
输出,表明%d
运算符正在执行正确的操作(始终向下舍入到最接近的整数)。