- ベストアンサー
PHPで~を使うときのビットの認識の仕方について
~演算子を使用する際の、ビットの認識のされ方についてなのですが ~演算子の動作がよく理解できなかったので、色々試してみたところ、以下のような感じでした。 ~1 = -2 ~0 = -1 ~37 = -38 この結果から色々逆算してみることにしました。 例えば-38ですが、この-38はコンピューター上では2の補数のビット列で構成されているはずで、そのビット列は 1000000(2)-100110(2)(=38) という式の答えに、最上位ビットに識別子「1」をつけたビット列であるはずです。 つまり、-38のビット列は1011010(2) ということになると思います。 で、この1011010(2)というビット列は、~演算子によって生成されたものなので、反転される前は 0100101(2) というビット列だったということになると思います。 この 0100101(2) は10進表記に直すと37(10)となるので、 冒頭の~37 = -38 が証明されたことになると思います。 ただ、1つ気になるのは、反転される前のビット列が0100101(2) という、最上位ビット列に0が付けられたビット列として認識されているということです。 37の2進表記は一番簡単に考えれば100101(2)ですが、このビット列でビット反転させると、1011010(2)(=-38)ではなく011010(=26)というビット列になってしまい、、-38になりません。 ~1 や ~0 の場合でも同様で、最上位ビットに0が付いてないと仮定すると、辻褄があわなくなります。 冒頭の通り、~37は-38を返すので、評価したビット列は0100101(2) であるはずです。 上記のようなことから、PHPの~を使用する場合、評価されるビット列は必ず最上位に0が付されるという結論に至ったのですが、この理解で正しいでしょうか? わかりにくい文章ですいません。 どなたか詳しい方いらっしゃいましたらご教授よろしくお願いします。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
がると申します。 んと…非常にしっかりした理論思考をお持ちなようなので、一回目はあえて「ヒント」だけ。 こういったときに二進数表現するときは、桁数に気をつけます。 具体的には。通常、昨今は32bitCPUが多いので。二進数は常に32桁で考えてみましょう。 そうすると、2の補数による負の値の「二進数表現」が変わりませんか?
その他の回答 (5)
- php504
- ベストアンサー率42% (926/2160)
PHPには2進数で表示する方法があったので <?php printf("%b", ~37); ?> で確認できます。
お礼
お礼が遅れてすいません。 printf("%b", ~37)で確認してみました。 ありがとうございましたm(_ _)m
- noocyte
- ベストアンサー率58% (171/291)
> 32bitCPUで表現できる数字の範囲は-2147483648~2147483647?? PHP の整数型は符号付1種類だけ (だそう) なので, 32ビットであればそのとおりですね. しかし 32bit CPU は普通,無符号32ビット整数や, 16ビット,8ビット整数なども扱えます. 整数型 (Wikipedia) http://ja.wikipedia.org/wiki/%E6%95%B4%E6%95%B0%E5%9E%8B > ~演算子で引数が評価される時、その引数が負数の場合は、 > 最上位ビットに符号ビットである「1」が付せられ、 > 逆に正数の場合は「0」が付せられる。 × 引数は「評価される時」ではなく最初から32ビットで, ~ 演算子はただその全ビットを反転させるだけです. まだ固定ビット長で考えることに慣れていませんね.(笑) ちなみに PHP では使わないかもしれませんが, ↓この言葉も知っておきましょう. 符号拡張 (Wikipedia) http://ja.wikipedia.org/wiki/%E7%AC%A6%E5%8F%B7%E6%8B%A1%E5%BC%B5
お礼
お礼が遅れてすいません。 > 引数は「評価される時」ではなく最初から32ビットで・・・ ようやく分かってきました。 その他の事項についてもご親切に、ありがとうございました。 とても勉強になりました。
- php504
- ベストアンサー率42% (926/2160)
>つまり、-38のビット列は1011010(2) ということになると思います。 正しい場合もあるでしょうが(7ビット処理系はあまりないですけど)そうでない場合がほとんどだと思います。 PHPの内部では1011010(2)は90(10)です。
補足
多くの場合は-38(10) は 11111111 11111111 11111111 11011010(2) ということでしょうか。 回答ありがとうございましたm(_ _)m
- めとろいと(@naktak)
- ベストアンサー率36% (785/2139)
http://www.jtw.zaq.ne.jp/kayakaya/new/kihon/text/fusu.htm #1さんの回答をもとに、このサイトの最初の5,6行を読めば理解出来るでしょう!
補足
上のURLのページは見たことがあったのですが、ちゃんと読めてませんでした。回答ありがとうございますm(_ _)m
- noocyte
- ベストアンサー率58% (171/291)
回答を書こうと思ったのですが,#1 さんがヒントだけ ということなので,私も1回目はヒントだけ….(笑) > PHPの~を使用する場合、評価されるビット列は必ず最上位に0が付されるという > 結論に至ったのですが、この理解で正しいでしょうか? 負数に ~ を付けるとどうなりますか?
補足
回答ありがとうございます。 No1の方の補足のところに出した答えを書きました。 負数に~を付けたら?というのがとてもヒントになりました。
補足
回答ありがとうございます。 No2、No3の方が下さったヒントも踏まえて理解できた気がします。 要するに、PHPでは 00000000 00000000 00000000 00100110(2) のビット列が38(10)と認識され、よって-38は2の補数表現によって 11111111 11111111 11111111 11011010(2) と表現される。このビット列をビット反転させた00000000 00000000 00000000 00100101(2) は、10進表記に直すと37になるので、~37=-38 が証明される。 ~演算子で引数が評価される時、その引数が負数の場合は、最上位ビットに符号ビットである「1」が付せられ、逆に正数の場合は「0」が付せられる。 符号ビット「0」又は「1」は、32ビット列の1ビット目に割り当てられ、よって実際の数字は2ビット目以降の31個のビットによって表現されている。(※疑問点 よって、32bitCPUで表現できる数字の範囲は-2147483648~2147483647?? MySQLではbigint型のカラムで9223372036854775807 まで格納できるが・・?) という感じでよろしいでしょうか。