はじめまして、開発部の小泉です。
今回の記事ではPHPで数字を使わずに0~10を作る方法について説明します。
はじめに
PHPで echo true
を実行すると、「1」が出力されます。
ふとこれを使えば、数字を一切使わずに他の数字も作れるのではないかと考え、実際に試してみました。
ただ作るだけでは面白くないので、以下のような制約を付けました。
1. 型がintになること(var_dumpで確認)
2. 可能な限り短くすること
3. 定数は使わない(簡単になりすぎるので)
PHPがわかる方は、どんなコードになるのか予想してみて下さい。
文中のコードが正しいのか試してみたい方は、下記のサイトにコピペすると簡単に試すことができます。
⇒ https://3v4l.org/
1と0
冒頭で示した echo true
は、見た目は1ですが、内部的にはbool型になります。
intにキャストする必要がありますが、一般的に使われるintval()
は長いので、演算子+を使用します。
また、「true」は4文字もあるので”(空文字列)に!を付けることで3文字に短縮できます。
falseも同様に作成してintにキャストすることで、0も作ることができます。
結果が以下のコードです。
var_dump(+!!''); //0 var_dump(+!''); //1
ビット否定(2)
2は1+1ではなく、ビット否定演算子~
を使って作ります。
ややこしいので説明を省略しますが、整数nをビット否定すると-(n+1)になります。(気になる方は2の補数で調べてください)
符号は-を付ければ反転できるので、-~
は「正の数をintにキャストし1加算する」ことができます。
これは頻出テクニックなので覚えておいてください。
var_dump(-~+!''); //2
円周率(3~5)
3といえば円周率pi()
ですよね。そのままだとfloat型で3.14・・・になってしまうので、intにキャストします。
ビット演算子はintにキャストしてくれますので、~~
のようにビット否定を2個並べることで切り捨てができます。
円周率とビット否定を組み合わせることで、3~5が作れます。
var_dump(~~pi()); //3 var_dump(-~pi()); //4 var_dump(-~-~pi()); //5
ビットシフト(6~9)
6は3の2倍になります。普通は*を使いますが、2(-~+!''
)が6文字もあるので、代わりにビットシフト<<
を使います。
2のべき乗を掛けることになるので、6は3<<1
、8は1<<3
でそれぞれ表現できます。
7,9は6,8をそれぞれ1大きくすればいいのですが、演算子の優先順位があるので、かっこでくくる必要があります。
var_dump(pi()<<!''); //6 var_dump(-~(pi()<<!'')); //7 var_dump(!''<<pi()); //8 var_dump(-~(!''<<pi())); //9
16進数(10)
10は16進数だとaとなり、数字を使わずに表現できます。
これまでと違い、読みやすいコードではないかと思います。
var_dump(hexdec('a')); //10
まとめ
最後に今までのコードを再掲します。
var_dump(+!!''); //0 var_dump(+!''); //1 var_dump(-~+!''); //2 var_dump(~~pi()); //3 var_dump(-~pi()); //4 var_dump(-~-~pi()); //5 var_dump(pi()<<!''); //6 var_dump(-~(pi()<<!'')); //7 var_dump(!''<<pi()); //8 var_dump(-~(!''<<pi())); //9 var_dump(hexdec('a')); //10
可読性が非常に悪いコードになったのではないでしょうか。
ビット否定や演算子の優先順位など、普段は意識しないところを詳しく知るきっかけにもなりました。
こういった普段のプログラミングと全く違うことを考えると頭の体操になって面白いですね。