• ベストアンサー

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が付されるという結論に至ったのですが、この理解で正しいでしょうか? わかりにくい文章ですいません。 どなたか詳しい方いらっしゃいましたらご教授よろしくお願いします。

  • PHP
  • 回答数6
  • ありがとう数5

質問者が選んだベストアンサー

  • ベストアンサー
  • galluda
  • ベストアンサー率35% (440/1242)
回答No.1

がると申します。 んと…非常にしっかりした理論思考をお持ちなようなので、一回目はあえて「ヒント」だけ。 こういったときに二進数表現するときは、桁数に気をつけます。 具体的には。通常、昨今は32bitCPUが多いので。二進数は常に32桁で考えてみましょう。 そうすると、2の補数による負の値の「二進数表現」が変わりませんか?

miraikako
質問者

補足

回答ありがとうございます。 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 まで格納できるが・・?) という感じでよろしいでしょうか。

その他の回答 (5)

  • php504
  • ベストアンサー率42% (926/2160)
回答No.6

PHPには2進数で表示する方法があったので <?php printf("%b", ~37); ?> で確認できます。

miraikako
質問者

お礼

お礼が遅れてすいません。 printf("%b", ~37)で確認してみました。 ありがとうございましたm(_ _)m

  • noocyte
  • ベストアンサー率58% (171/291)
回答No.5

> 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

miraikako
質問者

お礼

お礼が遅れてすいません。 > 引数は「評価される時」ではなく最初から32ビットで・・・ ようやく分かってきました。 その他の事項についてもご親切に、ありがとうございました。 とても勉強になりました。

  • php504
  • ベストアンサー率42% (926/2160)
回答No.4

>つまり、-38のビット列は1011010(2) ということになると思います。 正しい場合もあるでしょうが(7ビット処理系はあまりないですけど)そうでない場合がほとんどだと思います。 PHPの内部では1011010(2)は90(10)です。

miraikako
質問者

補足

多くの場合は-38(10) は 11111111 11111111 11111111 11011010(2) ということでしょうか。 回答ありがとうございましたm(_ _)m

回答No.3

http://www.jtw.zaq.ne.jp/kayakaya/new/kihon/text/fusu.htm #1さんの回答をもとに、このサイトの最初の5,6行を読めば理解出来るでしょう!

miraikako
質問者

補足

上のURLのページは見たことがあったのですが、ちゃんと読めてませんでした。回答ありがとうございますm(_ _)m

  • noocyte
  • ベストアンサー率58% (171/291)
回答No.2

回答を書こうと思ったのですが,#1 さんがヒントだけ ということなので,私も1回目はヒントだけ….(笑) > PHPの~を使用する場合、評価されるビット列は必ず最上位に0が付されるという > 結論に至ったのですが、この理解で正しいでしょうか? 負数に ~ を付けるとどうなりますか?

miraikako
質問者

補足

回答ありがとうございます。 No1の方の補足のところに出した答えを書きました。 負数に~を付けたら?というのがとてもヒントになりました。

関連するQ&A

  • 教えてください4

    初心者なのでわかりやすくお願いします。 16ビットの場合の2の補数を求めるプログラムをポインタを使用して 作成せよ。 2の補数→簡単に言うと2進数表記の各ビットを反転して1を足した値 (例)36の2の補数、8ビットの場合 1.36(10進数)→00100100(2進数表記) 2.各ビット反転→11011011 3.下位1ビットに1を足す→11011100(36の2の補数) <実行結果> 10進数を入力:12 2の補数へ変換 0000000000001100 -> 1111111111110100 2の補数は1111111111110100です。

  • ビットやバイトの計算がわかりません

    何度読んでも理解できません。 (1)ビット列A=111011、ビット列B=110110、ビット列C=010011に対し、A+(B・C)の結果は何になるか? (2)ビット列A=111010、ビット列B=010110、ビット列C=011011に対し、(A+B)・Cの結果は何になるか? (3)2進数Xの1の補数は101101、2の補数はYになる。 XとYを求めよ (4)2進数Xの1の補数は1011001、2の補数はYになる。XとYを求めよ 答えよりも、解き方や考え方を詳しく教えてください。 全くわかりません。 また、これらを解くのに必要な知識、などありましたら、併せて教えてください。

  • 2進数の補数表示について

    よろしくお願いします 「負の数(-128)を8ビットの2の補数表示するとき、どうなるか?」 の問題で、わからない箇所があります。 1.最上位ビットは正・負を表す。 2.負の数:-127を2の補数を使用して表現する。    (例)-1(10)==>    まず、正で考える。      ==> 0000 0001(2)      「確認」 1111 1110(反転)            +1(プラス1) ---------- 1111 1111(2)(答え) -127(10)      ==>0111 1111(2)  まず、正で表す。    「確認」        1000 0000(反転)           +1 (プラス1) ---------- 1000 0001(答え) ここからが疑問なんです。    -128(10)の場合      ==>1000 0000(2) まず、正で考える。    「確認」        0111 1111(反転) +1 (プラス1)       -----------      1000 0000(2)(答え) ↑ ・答えがプラスの128(10)=>10000000(2)と同じではない  でしょうか? ・このときの最上位ビットは桁上がりの「1」と正負の違  いを表す「1」のどちらを表しているのですか? ・たとえば「負数を2の補数で表すとき,8ビットで  表現できる整数の範囲は10進数でどれか。」など  の問題で答えが正の127は理解できるのですが、  負は「-128」ということがよくわかりません。 一応検索をしてみましたが、類似回答では理解できませんでした。よろしくお願いします。        

  • 16ビットの2進数の、2の補数を求める操作

    16ビットの2進数の、2の補数を求める操作として、以下のうち、適当なものはどれなのか、わかりません。 ・(FFFF)16とANDをとる ・(0001)16とORをとる ・(FFFF)16とEORをとる ・(0001)16とORをとったあと、(0001)16を加える ・(FFFF)16とEORをとったあと、(0001)16を加える マイナスの数は、2の補数で表します。 0と1を反転させたものに、1を足します。 また、論理計算も、論理積、論理和、排他的論理和は理解しています。 2の補数の求め方は分かるのですが、以上の問題になると、とたんに解けなくなります。 どなたか教えていただけませんでしょうか。

  • ソフ開の問題集について

    こんにちは。さっそくですが質問させていただきます。 日高哲郎氏の著作 「2006秋 ソフトウェア開発技術者 午後問題集」 の第二章アルゴリズム 演習4 BNF についてなのですが、 構文規則で定義される 言語のなかで byte 8ビット 補数表現の整数 short 16ビット 補数表現の整数 char 16ビット 符号なし整数 int 32ビット 補数表現の整数 を扱うのようなのですが <演算子> の定義の中にシフト演算子があり、 '<<' 空いたビットに符号ビットを入れる '<<<' 空いたビットに 0 を入れる とありました。 ----------------------------------------------------- 設問4の(2) の問題文はつぎのようなものでした。 シフト演算子<< は(1)のように除算演算子で置き換え可能である [ (1) については省略させていただきます。] ~中略~ 除算演算子をシフト演算子に置き換え可能なのは 除数および被除数がどのような場合か ----------------------------------------------------- 正解は 除数 2 のべき乗のとき 被除数 char型で32767以下の場合、またはchar型以外のとき なのですが、これはそれぞれの型においての最上位ビットの 扱いからだと思うのですが、 ( char型以外は 2 の補数表現の整数 ) 質問させていただきたいのは本の正解に対する 解説についてなのです。 ----------------------------------------------------- 解説文においては 「・・・符号ビットを意識しないchar型であると 最上位ビットに 1 が入っていると右シフトの結果空いたビットに 0 が入ってしまうため数値としてみた場合、正しい結果が得られない。 ・・・」 とあるのですが、空いたビットに 0 が入れば数値として 正しくなるのではないでしょうか? そしてこの場合、char型の最上位ビットに 1 が入っていると シフトしたら、空いたビットに 1 が入るので数値としては 正しくなくなるのではないでしょうか? 自分の理解に自信が持てないので、このような質問を させていただきましたが、 ご存知のかた、教えていただけないでしょうか? よろしくおねがいします。

  • おしえてください<(_ _)>

    C言語を学んでいる初心者です。ビット補数演算子という分野で反転させた値にできるそうなんですがint型で整数は7を反転させて10進数で表すと-8になると書いてありました。私が2進数から10進数に直したら+の数になりました。 詳しい方教えてください<(_ _)><(_ _)>

  • コンピュータはなぜ減算ができないのか?

    たとえば コンピュータでは2-1を補数を利用して計算します。 しかし、繰り下がりの概念があれば以下のように 直接計算できるはずです。    0010 -) 0001 -----   0001 元々コンピュータには、繰り下がりに対応する演算回路が ないので、引き算が足し算のように簡潔にできない と思ってよいのでしょうか? また、掛け算は足し算のループを利用して計算しているのでしょうか? 割り算は、2の補数(ビット反転+1)の引き算をループさせて実現しているのでしょうか? ということは、計算のうち割り算が一番時間がかかると思ってよいのでしょうか?

  • 2進数 問題の意味

    課題で以下のような問題が出されました。 …が、何をすれば良いのか、何が問われているのかが全くわかりません。 詳しく教えて頂けませんでしょうか。 問1.2進数の(11010110)2 を(00101001)2 にビット反転するためにどのような論理演算を行えば良いか。 (11010110)2 の2は右下に小さく表記されています。 この書き方も初めて見ます。 問2.2進数の(1101/0110/0001/1101)2 の右端の4ビットだけを取り出したい。するためにどのような論理演算を行えば良いか。 (1101/0110/0001/1101)2 この書き方も初めてです・・・

  • byte[2] から int へ。

    それぞれintの下位2バイトのビット列保持するbyte型配列の要素2つを int 形の整数に治したいのですがいい方法が思いつきません。例えば、 byte[0] = 0x01; byte[1] = 0x01; ならば、 00000000 00000000 00000001 00000001 で、256 + 1 = 257 byte[0] = 0x02; byte[1] = 0x10; ならば、 00000000 00000000 00000010 0000011 で、512+3 = 515 です。byteの値が0~127の場合は int n = byte[0] << 8 n = n | byte[1] という感じでいけそうなのですが、byte[0]が 0xFF のような負の値のときにint とのビット演算(もしくはシフト演算)で上位2バイト分も補数表記のためか全部1で埋まってしまい、上の方法はだめみたいです。 byte[0] = 0x01; byte[1] = 0xFF; のときは、 00000000 00000000 00000001 11111111 で、256+255 = 511 としたいのですが、場合わけをせずに求める よい方法はないでしょうか。

    • ベストアンサー
    • Java
  • C言語のビット演算子に関して

    はじめまして、今C言語の学習(半月ほど)を行っている者ですが ビット演算子のところで悩んでおります。 問題文に 変数cの2ビット目と3ビット目をONにする、 あるいはOFFにするといった表記がでてくるのですが このON、OFFとは何を意味しているのかいっこうにわかりません。 (私の考えではONとは1を意味しており2ビット目、3ビット目を ONにするとは -------------------------------------------------------------- ~1|1|0|0 (右から0ビット目、1ビット目、2ビット目、3ビット目) -------------------------------------------------------------- ということを言っているのではないだろうかと思っています。) ビットに関して私の勉強不足であることは十分に認識して おりますが、何かヒントをいただけるとありがたく思っています。 宜しくお願いいたします。

専門家に質問してみよう