Я столкнулся с интересной проблемой в моем коде "humanize_bytes()". Этот цикл представляет проблему без всякой другой логики. Цикл необходимо остановить, когда байты будут усечены до «удобочитаемого» уровня. Он продолжает повторяться до тех пор, пока окончательное значение не станет меньше 1024 (или заданного размера в байтах).
Я начал разбираться в проблеме, когда функция выдала "1024.0 P" для 1024 петабайт. Сначала я подумал, что случайно использую ‹= vs ‹, но при дальнейшем рассмотрении я обнаружил, что происходит нечто более интересное.
Этот код воспроизводит проблему. Я использую перл 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 использует десятичное представление.