PHP serialize () выводит число - PullRequest
4 голосов
/ 02 июля 2011

Я рассчитываю размер файла, загружаемого в PHP, для форматирования в МБ с одним десятичным знаком, например:

$metadata['upload_data'] = intval($_FILES['Filedata']['size'] / 104857.6) / 10;

Когда я echo $metadata['upload_data'], вывод 1.7, как я и ожидал. Но когда я сериализую массив с serialize($metadata) и сохраню его в файл, получится:

a:2:{s:7:"uploads";i:11;s:11:"upload_data";d:1.6999999999999999555910790149937383830547332763671875;}

Я пытаюсь быть эффективным, храня размеры файлов в МБ, а не в байтах, но это кажется хуже! Почему PHP хранит это таким образом? И я иду по этому пути правильно? Спасибо

Ответы [ 2 ]

3 голосов
/ 02 июля 2011

Из руководства: http://php.net/manual/en/language.types.float.php

Кроме того, рациональные числа, которые точно представлены в виде чисел с плавающей запятой в базе 10, например 0,1 или 0,7, не имеют точного представления в виде чисел с плавающей запятойв базе 2, которая используется внутри, независимо от размера мантиссы.Следовательно, они не могут быть преобразованы в их внутренние двоичные аналоги без небольшой потери точности.Это может привести к сбивающим с толку результатам: например, floor ((0.1 + 0.7) * 10) будет обычно возвращать 7 вместо ожидаемых 8, поскольку внутреннее представление будет примерно таким: 7.9999999999999991118 ....

Я бы предложил использовать json_encode и json_decode, если вы хотите увидеть «1.7» в сериализованной версии вашего массива.Эти функции также оказываются быстрее, чем serialize и unserialize, и их также легче читать (под более простым чтением я имею в виду человека, который их читает, а не машину).

1 голос
/ 02 июля 2011

Вы делаете предположения о том, как serialize работает.

Очевидный способ хранения double (и «float» в большинстве языков, отличных от C, будет double) - это использование 8 байтов. Насколько я знаю, большинство нормальных двоичных сериализаций будет делать это.

(Да, я немного злоупотребляю словом "double" для обозначения 64-разрядной двоичной плавающей запятой IEEE 754.)

Вместо этого PHP пытается сохранить десятичное представление, что затрудняется тем фактом, что невозможно точно представить 1.7 в двоичном виде. Оказывается, самое близкое представление точно 1.6999999999999999555910790149937383830547332763671875.

Я не знаю, почему PHP предпочитает давать точное представление вместо кратчайшего представления, которое преобразуется обратно в одно и то же двойное число (вам, разумеется, не нужно больше 17 цифр или около того, и есть более эффективные алгоритмы, чтобы сделать вас короче номера). Одна из возможностей состоит в том, что она хочет сохранить точную семантику в случае, если целевая система использует другое представление с плавающей запятой (например, если ваша целевая система использует 128-битные "двойные-двойные", 1.7 - это другое число).

Все это говорит о том, что 1700 - это только на один байт больше, чем 1.7, но предлагает гораздо большую точность.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...