I ran across an interesting issue in some of my "humanize_bytes()" code. This loop represents the issue without all the other logic. The loop needs to stop when the bytes have been truncated to a "human readable" level. It keep iterating until the final value is less than 1024 (or specifiable bytesize).
I started looking into the problem when the function output "1024.0 P" for 1024 petabytes. At first I thought I accidentally use a <= vs <, but upon further inspection I found that something more interesting was happening.
This code reproduces the problem. I'm using 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;
The output I receive is:
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
The thing to notice here is that the final value in decimal is 1023, but in float its 1024. How can that be? And obviously, perl is using the decimal representation.