0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PHP number_formatの挙動について

Posted at

PHPのnumber_formatを用いた計算にて

皆様、こんにちは。

先日、初歩的なのに気付けなかったミスがあり、自戒の念を込めて記事にさせて頂きます。

「こんなの当たり前!」って人もいるかと思いますが、記憶の定着にはアウトプットが良いということもあるので、しばしお付き合いくださいませ。

前提

  • PHPバージョン
    • PHP7.1

何が起こった?

表題、PHPのnumber_format()を用いた計算でうっかりがありました。

現プロジェクトで料金をフロントで表示する時に,区切りを付ける必要がありました。

int型の数値をそのまま表示ではマズイ訳です。

$a = 2000;
$b = 100;
echo number_format($a - $b); //1,900(string)

このような感じですね。

さて上記の既存式に追加修正で割引額を追加してくれとなりました。

本来なら…

# 省略
$discount = 200;
echo number_format($a - $b - $discount); //1,700(string)

とすべきですね。

ところが半年前(!?)の私は…

# 省略
echo number_format($a - $b) - $discount; //?(?)

としていたようです。

どうなってしまったのか?

すでに上記結果で書いているのですが、number_format()の戻り値はstringです。

ということは

# これは…
number_format(1900) - 200;
#こうなります
'1,900' - 200;

上記のような感じですね…よろしくないのが一目瞭然です…

結果

「でもPHPには 暗黙的型変換 があるんじゃ?」となりそうです。

これがうまく機能してしまえば(そもそも良くないのですが…)、1900 - 200となるはず…

ところがどっこい!結果は…-199(int)となります!

どうやらstringからintへの変換時に,を変換できずに1となってしまうようです。

暗黙的型変換時での,の扱いについては出典が見つけられず…公式ドキュメントのここだよというのを知っている方がいたら教えて頂きたいです…

ちなみにintval()でも同様の挙動なので、,が含まれている文字列数値はそこまでの数値になってしまうようですね。

所感

元々を考えれば)の位置を間違えなければ良かったように思えますがそこは人間、間違いもやっぱりあるはずです。

テストコードがあれば防げるかと思いきや、number_format()の引数が1000未満のテストケースだと引っ掛からないという…

ただ、カンマを付けた表示にしたいという仕様であるなら、カンマを付けた結果がどうなるかに考慮できればテストケースに落とし込めたようにも思えます。

やっぱりテストケース考慮は大事!という安直ではありますが、確実に必要な考えを学べただけでも良かったかなと思います。

おまけ

こういうイージーミスをコンパイル時に弾いてくれる静的言語はやっぱり魅力ですね…(PHPも良い言語ですけどね!)

0
0
2

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?