2011-07-02 4 views
4

である私はそうのような小数点以下1桁でMBにフォーマットするために、PHPでのファイルアップロードのサイズを計算しています:PHPシリアライズ()の出力は強打

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

Iが出力さ1.7としてあるecho $metadata['upload_data']とき私は期待しています。私はserialize($metadata)で配列をシリアル化してファイルに保存する場合でも、出力は次のようになります。

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

私はMBでないバイトのファイルサイズを格納することにより、効率的にしようとしているが、これは悪いことです!なぜPHPはそれをそのように保存しますか?そして私はこれについて正しいことをやっていますか?おかげマニュアルから

+4

Datはwhack fo shoです。 – Ben

+0

何か不足していますか?バイト単位で格納するよりも、MB単位で格納するほうが効率的ですか?彼らは同じベースユニットです... – rockerest

+0

あなたは 'json_encode'と' json_decode'を試すことができます。これは(un)serializeよりも速くなります。 – thetaiko

答えて

3

: は、0.1または 0.7ように、ベース10に 浮動小数点数として正確に表現されている浮動小数点 として正確な表現を持っていないことhttp://php.net/manual/en/language.types.float.php

さらに、有理数基数2の数字は 内部では、 の仮数のサイズに関係なく使用されます。したがって、 は、 の精度のわずかな損失なしで、対応する内部バイナリ に変換することはできません。これは混乱 結果をもたらすことができる:例えば、 フロア((0.1 + 0.7)* 10)は、通常の代わりに期待8の リターン7、 内部表現は

7.9999999999999991118 ....ようになりますので

アレイのシリアル化バージョンで「1.7」を表示する場合は、json_encodejson_decodeを使用することをお勧めします。これらの機能は、serializeunserializeよりも速くなり、読みやすくなります(読みやすくすると、コンピュータではなく読んでいるという意味です)。

+0

Aha!ありがとうございました、今私は理解しています – Tak

1

あなたは方法の仮定をしていますserialize

double(およびC以外のほとんどの言語では "float"をdoubleにする)を格納する明白な方法は、基になる8バイトとしてです。私が知る限り、ほとんどの正気なバイナリシリアル化がこれを行います。

(はい、私は少しIEEE 754 64ビットの2進浮動小数点を意味する「ダブル」乱用しています。)

代わりに、PHPはそれが事実によって妨げられている10進表現を格納しようとしていますバイナリで1.7を正確に表す方法はありません。最も近い表現は、正確には 1.69999999999999555910790149937383830547332763671875です。

PHPが、同じ倍精度に変換する最短表現ではなく正確な表現を与える理由を知りません(17桁以上は必要ありません)。短い数字)。 1つの可能性は、ターゲットシステムが異なる浮動小数点表現を使用する場合(例えば、ターゲットシステムが128ビットの「double-doubles」を使用する場合、1.7が異なる数)、正確なセマンティクスを保持したい場合です。

1700は、1.7よりも1バイト多いだけですが、はるかに高い精度を提供します。

関連する問題