LoginSignup
4
5

More than 5 years have passed since last update.

var_exportで浮動小数点数を人の目に優しい出力にする

Last updated at Posted at 2015-12-22

例によって小ネタです。

小数点以下n桁で四捨五入した小数をvar_exportでダンプしようとしてみた

ソースコード
$a = 3.1419526535;
var_dump(round($a,2));
echo var_export(round($a,2),true) . PHP_EOL;
結果
float(3.14)
3.1400000000000001     <------- Σ(゚Д゚)

何がいけなかったの?

困った時はPHPマニュアルを参照参照...特に何も書いてないな。
じゃあStackOverflowさんに聞いてみるか…

php, var_export fails with float

wtf?(What the fuck, 何だコレ?)だって

確かに何だコレ。です。

ここに書かれてある「serialize_precision」がクサイ。

そこでもう一度マニュアルのコメント欄まで見てみると、PHP5.4.22からiniファイルの「serialize_precision」を見るようになった。デフォルトは17だよと書いてた。

なんで17?と思いつつ、じゃあ精度下げてみるかってことに。

とりあえずの解決方法

ソースコード
ini_set('serialize_precision', 16);
$a = 3.1419526535;
var_dump(round($a,2));
echo var_export(round($a,2),true) . PHP_EOL;
結果
float(3.14)
3.14     <------- (ー。ー)フゥ

serialize_precisionを16以下にするといいみたいです。

serialize_precisionについて

こちらに「すごくシンプルな」説明がありました。

浮動小数点数をシリアライズするときに格納する桁数を指定します。

シリアライズ?ってことは、ひょっとするとserializeにも影響するの?json_encodeも怖いから確認してみましょう。

ソースコード
ini_set('serialize_precision', 17);
echo serialize(round($a,2)) . PHP_EOL;
echo json_encode(round($a,2)) . PHP_EOL;

ini_set('serialize_precision', 16);
echo serialize(round($a,2)) . PHP_EOL;
echo json_encode(round($a,2)) . PHP_EOL;
結果
d:3.1400000000000001;
3.14
d:3.14;
3.14

serializeには影響しましたが、json_encodeには影響しませんでした。どういう理屈なんだろう?

serialize_precisionのデフォルト値の意味

よくわからないのですが、マニュアルの浮動小数点の説明に

PHP は通常 IEEE 754 倍精度フォーマットを使います。 この形式は、1.11e-16 のオーダーでの丸め処理で誤差が発生します。

とあるのですが、これと関係ありそうな気もします。
(詳しい方のコメントお待ちしています!)

結論: floatな値をvar_exportしたとき人の目に優しく出力するには「serialize_precision」を設定するべし

でもserialize_precisionはグローバルなので、他の箇所に影響しないよう注意してくださいね!

ちなみに

この記事はPHP Disではありません!(笑)

4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5