2010/03/20

ビットを見つめる Part6 -理解・分解・再構築-

と、いうわけで、これまでの勉強で

「補数とは何か」
「intのマイナスはどうやって保持されているか」

というものを理解できたと思います。

それでは、実際にARGBのカラー値を抜き出してみましょう。

はーい。

ここでビットシフトの話になりますが、ビットシフトはご存知ですか?

ビットの値を左か右にずらすんだよね。

まぁ、そういうことです。

種類はそれぞれ
「<<」(ビット単位の左シフト演算子)
「>>」(ビット単位の右シフト演算子)
「>>>」(ビット単位の符号なし右シフト演算子)
があります。

例えば
「0×1234」という16ビットをそれぞれの演算子で扱ってみましょう。
まず「0×1234」は「0001001000110100(2)」です。

「<<」は左側に指定の数だけシフトします。
例えば「0×1234 << 2」であれば、
「0001001000110100(2) << 2」ということであり、
0100100011010000(2)となります。ビットが左に2ビット分動いて、右を0で埋めた感じですね。

これ、あふれたらどうなるの?破棄されるの?

その通りです。あふれたものは破棄されます。
例えば「0×1234 << 4」としてみましょう。
「0001001000110100(2) << 4」は、0010001101000000(2)となります。

最上位から4つ目のビットまでが消えて、その分最下位から0が4つせり上がってくるんだね。

そういうことです。考え方は簡単ですよね。

では、次は「0×1234 >> 2」ですね。
「0001001000110100(2) >> 2」ということであり、右に2ビットシフトするので、
「0000010010001101(2)」ということになります。

続いて、「0×1234 >>> 2」は、
「0001001000110100(2) >>> 2」ということであり、右に2ビットシフトするので、
「0000010010001101(2)」ということになります。

・・・?
同じじゃん?

そう、そこが今回の勉強内容です。

では、「0xABCD >> 6」、「0xABCD >>> 6」の場合を考えてみましょう。
それぞれどうなると思いますか?

・・・両方同じ?

いえ、残念ながら違います。
まず、0xABCDは、「1010101111001101(2)」ですね。

で、両方とも右にずらすのは同じです。
問題は、「符号付きのビットシフト」か「符号なしのビットシフト」か、ということです。

intの話を思い出してください。
符号はどこで判断できましたか?

最上位ビットが0だったら正の数で、1だったら負の数だったよね。

そうです。結論から言いますと、「>>>」の場合は「<<」のように、空いた分は必ず「0」で埋めます。

しかし、「>>」の場合は「符号ありの右シフト」なので、ビットシフトしても符号が反転しないように、最上位ビットが0であれば左に0を埋め、1であれば左に1を埋めます。

ということは・・・?

「1010101111001101(2) >> 6」は「1111111010101111(2)」で、
「1010101111001101(2) >>> 6」は「0000001010101111(2)」っていうことか!

そう、その通りです。数が全く異なってしまうことが判ると思います。

さて、それでは実際に色を分解してみましょう。

「0×98765432」というARGBのカラー値があります。これをARGBに分解してください。実際にAS3で作ってみてくださいね。

また、実際に2進数でも書いて、その経緯を示してください。

はーい。

まず、
var color:uint = 0×98765432;
で、色を定義して・・・。

2進数だと「0×98765432」は「10011000011101100101010000110010(2)」。

ARGBの色はuintで表現されるから、符号とか関係ないし、「>>>」を扱った方がいいのかな。

ということは、Aを抜き出す場合は、
「color >>> 24」で「00000000000000000000000010011000(2)」。

Rを抜き出す場合は・・・どうするの?
「color >>> 16」でRを下位8ビットに持っていくことはできるけど、このままだとAも交じってしまうんだけど・・・。

&演算子を使うことによって、フィルターを掛けることができます。
詳しくは省略しますが(気になる方は「ビット演算 演算子」等で検索してみてください。)、
例えば10101010(2)に&演算子で00001111(2)をかけてやると、00001010(2)となります。

えーと、つまり、同じビットのところに&で0をかけてやると、そこは0になる感じなのかな。

ということは・・・。
「color >>> 16」で「00000000000000000000010111100011(2)」になって、
それに0×000000FFを&で掛けてやればいいのか。

0xFFでいいですよ。0×000000FFと同じことなので。

お、了解!
ということは、つまり、「(color >>> 16) & 0xFF」で、「00000000000000000000000001110110(2)」。

んじゃ、Gも同じだね。
「(color >>> 8 ) & 0xFF」で、「00000000000000000000000001010100(2)」。

Bは、このフィルター掛けてやるだけでいいね。ということは、
「color & 0xFF」で、「00000000000000000000000000110010(2)」。

で、これらを10進数に直すと・・・。
A=152、R=118、G=84、B=50!
これでARGBそれぞれの値を取れた!

そういうことです。
ちなみに、Aの値を「color >> 24」でとると、「-104」で取れてしまいます。
これは実際にどのように計算されたことになりますか?

0×98765432は「10011000011101100101010000110010(2)」で、最上位ビットが1だから、1で埋めることになっちゃうね。

つまり、>>で24個シフトしたら「11111111111111111111111110011000(2)」になってるってことだよね。
で、この値は、intで表現すると、2の補数が「00000000000000000000000001101000(2)」で、104(10)だから、0-104で-104!

そう、そういうことですね。よく出来ました。
しかし、実は>>を使っても正確にAが取れる方法があります。

ビットをよく見てください。「>> 24」であろうが、「>>> 24」であろうが、左側が0で埋められるか1で埋められるかの違いで、下位8ビットは同じになりますね。

ということは、「& 0xFF」を最終的に計算することによって、「>> 24」でもAが取れることになりますね。

おー、なるほどー。どういう風にビットが表現されてるかわからないと、これは確かに判らないね。

・・・でも、colorはuint型なのに、traceするとint型でしかトレースされないんだね。

そのようですね。もしuint型で表すなら「4294967192(10)」になりますね。

一応、「trace(uint(color >> 24));」のようにuintに変換してやると、上の数字で出てきますが。本来ならこのようなことをしなくてもuintで出てきてほしいところですね。

まぁでも、これですっきりしたよ!勉強になった!
やっぱり、ビットが実際にどういう風になってるかっていうのが判らないと、ビット演算を扱うのは危険なんだねー。

そうですね。その分、きちんと扱えれば、スクリプトの実行速度の向上にもつながりますし、色の分解のような、ビット演算でしかできないことも行えます。

まだまだ奥が深いビット演算、もしご興味があれば、また一つ、新たなステージに挑戦してみるのもありだと思いますよ。

さて、それでは、目標であった「色の取り出しメソッド」です。以下のコードをご覧ください。これにてこのお話は終了となります。お疲れさまでした。

package
{
 import flash.display.Sprite;
 
 public class Main extends Sprite
 {
  private var color0:uint = 0x81; //B
  private var color1:uint = 0x5d3; //GB
  private var color2:uint = 0xf438ef; //RGB
  private var color3:uint = 0xf8a13c8b; //ARGB

  public function Main()
  {
   trace(splitColor(color0)); //129
   trace(splitColor(color1)); //5,211
   trace(splitColor(color2)); //244,56,239
   trace(splitColor(color3)); //248,161,60,139
  }

  /**
   * 色の数値を分解し、分解した色を配列で返します。パラメータにARGBの色を渡した場合は[A,R,G,B]、RGBの場合は[R,G,B]、GBの場合は[G,B]が返されます。
   *
   * @param color 分解したい色の数値。
   * @return 分解された色を格納した配列。
   */
  private function splitColor(color:uint):Array
  {
   var len:int = Math.ceil(color.toString(2).length / 8);
   var returnArray:Array = [];
   
   for (var i:uint = 0; i < len; i++)
   {
    returnArray[i] = (color >>> (8 * (len - (i + 1)))) & 0xFF;
   }
   
   return returnArray;
  }
 }
}

「俺たちの戦いはまだこれからだ!」ということで、お付き合いいただきありがとうございました。

Tags: ,

2010/03/19

連休目前ですね

連休はコーディングしないと、いろいろ間に合わない。まだ、来週水曜までにやることが3つあるよ。

108 1900 を早口で言うと竜巻旋風脚に聞こえる、らしいけど、相当早く言いつつ、滑舌悪く言わないとだめなんじゃないか?

桑田佳祐の「ひとり紅白」のDVDが届きました。DVD2枚組。ボリューム満点です。早速視聴中。やっぱいいなー。

そして今月使えるお金も大分減ったー。

更に、見てたら3時になったー寝不足になったー。

ソニーの人に少しFeliCaProxyのことが聴けたんで、今日中にクラスライブラリ作るよ。できればだけど。

オウム真理教(アレフ)がmixiなどで勧誘活動 事件を知らない「ゆとり世代」に狙い
http://blog.livedoor.jp/himasoku123/archives/51451566.html

巷で話題になりまくりの「田中宏和さん」とはいったい?
http://labaq.com/archives/51414983.html

小道具のワインボトルで頭を殴るミュージカルのワンシーンにて、間違えて本物のボトルで殴るハプニング
http://www.kotaro269.com/archives/51008890.html

ゲーム大好き声優陣によるディープなトークを丸ごとCD化
http://www.ota-suke.jp/news/37566

ローソンで「Lチキ」発売1周年キャンペーン、100円で販売&くじ引きを展開
http://www.garbagenews.net/archives/1309104.html

爆問・田中、元妻が出産間近…法律上実子に
http://hochi.yomiuri.co.jp/entertainment/news/20100318-OHT1T00055.htm
でもこれって、結局離婚前に「ヤっちゃってた」ってことでしょ?二重でショックだわ、これ。

携帯電話によるFeliCa リード機能 (FeliCa カード読み取り機能)
http://blogs.itmedia.co.jp/ozeki/2010/03/felica-felica-7.html?ref=rssall

スクエニ、iPhone/iPod touch用完全新作RPG 「ケイオスリングス」
http://www.i-mezzo.net/log/2010/03/18222141.html

終了まで1年4ヶ月、テレビ局各社がアナログ放送の画面に「黒帯」を導入へ
http://gigazine.net/index.php?/news/comments/20100318_analog_tv/

キヤノンが新トップレベルドメイン名「.canon」の取得活動を開始
http://web.canon.jp/pressrelease/2010/p2010mar16j.html

『radiko』にニコニコ風の書き込みが出来るサービス 『ラジちゃんねる』 誕生!
http://rocketnews24.com/?p=27675&utm_source=feedburner&utm_medium=feed

量子力学的見地から考えたノーパンの扱いについて
http://ayacnews2nd.com/archives/51607511.html

競艇のウェブサイトが萌え化! 壁紙までダウンロード可能に?
http://alfalfalfa.com/archives/389390.html
別に今に始まったことではないらしい。

Tags: ,

2010/03/18

ビットを見つめる Part5 -毎日毎日の足跡がおのずから補数の答えを出す-

さて、では答え合わせをしましょうか。
ちゃんとできましたか?

ばっちりだよ!

ほほぉ。自信まんまんですね。それでは、実際に解き方を説明してもらいましょうか。

・・・ぇー・・・。

なお、前回書いたように、断りのない限り、「2の補数を使った符号付き8ビット」を前提に問題を出しています。
注意してくださいね。

では、まず問1を・・・

んー。まず、その前に一つ!

なんでしょう?

まず、「2の補数を使った符号付き8ビット」の最大値、最小値をそれぞれ求めてた方がいいと思うんだよね。

ほぉほぉ。なるほど。いいアプローチですね。いいですよ。

じゃ、始めるよー!
最大値は最上位ビットが0で全部1だから、01111111(2)で、これは127(10)だね。

最小値は、前回のを見る限り、最初が1で残り0だから、10000000(2)。
で、この数値と2の補数を合わせたものが0になるのだから、まずこの2の補数を求めて・・・。
2の補数は(2-1)の補数、つまり1の補数に1を足したものだから、
01111111(2)+1で、10000000(2)、で、これは128。
ということは、10000000(2) + 128(10) = 0から、10000000(2)は-128(10)。
というわけで、最小値は-128!

おお、素晴らしい。ちゃんとやりかたも覚えてましたね。
しかし、参りましたね、これを先にやられると、問題が半分くらい正解出たも同然なのですが。

・・・まぁいいでしょう。とりあえず問題を解いていきましょうか。

まず、問1 「-128」を2進数で表してください。
・・・と、これは、先程出されてしまいましたね。10000000(2)ですね。

ふふん。

んじゃ、次行きましょうか。
問2 「-90」を2進数で表してください。

90(10)を2進数に直した時の基数の補数が-90(10)ってことになるよね。
ということは、まず、90(10)は01011010(2)だね。
そしたら、基数の補数である「2の補数」は10100101(2)+1で。
-90(10)は10100110(2)!

正解です。いい調子ですね。

問3 「-1」を2進数で表してください。
・・・言っておきますけど、ちゃんと計算して解いてくださいね?

・・・ちっ・・・。

えーと・・・。
00000001(2)の「基数の補数」だから、11111110(2)+1で、11111111(2)だね。

お、だいぶスピーディーになってきたんじゃないんですか?
その調子で次に行きましょう。

問4 「0」を2進数で表してください。

これ、00000000(2)じゃん?
ひねって・・・ないよね・・・?

はい、ひねりはなにもないです。正解です。
では、問5は・・・。

・・・ねぇ、面倒だから、一緒に問6もいい?

いいですよ。そしたら、改めて。
問5 「-50」を2進数で表してください。
また、問6 「50」も一緒に2進数で表してください。

まず問6は、50は00110010(2)だね。
んで、問5は、00110010(2)の基数の補数だから、11001101(2)+1で11001110(2)!

正解です。もう流れも知識も大丈夫な感じですね。でも、一応全部やりましょう。
問7 「127」を2進数で表してください。
・・・は、最初に解いてしまったようなものだから、いいですね。
01111111(2)ですね。

では、続けて。
問8 「-140」を2進数で表してください。

これ、引掛け問題だよね?最初で出した最小値より低いから、8ビットでこれは表現出来ない!
表現しようとすると、01110100(2)になって、116(10)で表現されちゃうよね。

お、さすが、よくわかりましたね。それでは、最後の問題です。
問9 2の補数を使った符号付き24ビットにおける、正の数の最大、負の数の最小はそれぞれなんでしょう。

考え方は最初のやり方と同じだよね。
最大数は、011111111111111111111111(2)で、8388607(10)
最小数は、100000000000000000000000(2)で、
011111111111111111111111(2)+1で100000000000000000000000(2)で
0-100000000000000000000000(2)で、0-8388608だから、
-8388608(10)!

素晴らしい!全問正解ですね。

疲れた・・・。
みんなはできたかな?

今回の問題がこのように解けたのであれば、今までの話は全て理解していると考えていいと思います。
では、実際に次回は、実用問題をやってみましょう。正確にはビットシフトの勉強をします。
ビットシフトをちゃんと使うには、今までの知識が不可欠です。
今回で問題が解けなかった人は、ちゃんと復習して臨みましょうね。

やっときたねー。ワクワクするね!

というわけで、Part6 -理解・分解・再構築-をご期待下さい。

Tags: ,

2010/03/17

ビットを見つめる Part4 -練習は決して裏切らない-

さて、折角なので、ここで復習がてら、問題をやってみましょう。

断りのない限り、「2の補数を使った符号付き8ビット」を前提に問題を出します。

問1 「-128」を2進数で表してください。

問2 「-90」を2進数で表してください。

問3 「-1」を2進数で表してください。

問4 「0」を2進数で表してください。

問5 「-50」を2進数で表してください。

問6 「50」を2進数で表してください。

問7 「127」を2進数で表してください。

問8 「-140」を2進数で表してください。

問9 2の補数を使った符号付き24ビットにおける、正の数の最大、負の数の最小はそれぞれなんでしょう。

うーん、難しそうだねー。みんな解けるかなー?

あなたも解くんですよ?

・・・え?

Tags: ,

Flash用FeliCaSDKのaccess()用送信オブジェクトからみる、FeliCaSDKBasicで出来ること

と、銘打ってはいますが、正直よく判らんので誰か補足とかしていってくださると一層FeliCaの輪が広まるのではないかと思ったりしてます。
あと、Basic版のみです。Standardは持ってませんので。

せっかく少し勉強したので、っていうのと、なかなかASのFeliCa SDKに関する情報はないので、少しだけですけど、知ってることをまとめますよ。

FeliCaのアクセス流れを知らない人のために最初に書いておきますと、FeliCaをFlashPlatformで使う流れとして

ProxyOpen(FeliCaProxyにアクセス出来るようにする)

Hold(占有)

Open

やりたい処理

Close

Hold解除

ProxyClose

となります。(詳しいことはググってね!)

で、OpenとCloseに関しては、FeliCaにアクセスするときのみに必要で、モバイルへのアクセス(第3者通信?)やNFC Type3 Tagへのアクセスの場合は、わざわざOpenさせる必要はないっぽいです。ということは、Basicの場合だと、コンテナ情報を取るのとidmを取る時くらいですかね。

で、「やりたい処理」のところ以外の部分はほぼ「テンプレ」なので、SONYさんが公開されているサンプルコードをコピペして、あとは「やりたい処理」のところを自分のやりたい感じに書き換えればそれで済みます。はい。

まぁ、そんなわけで、ASDocに書かれてるクラス群はそれなりの量がありますが、実際に自分のオリジナリティを組み込むために必要なクラスは何かっていったら、かなり限られるわけです。少なくともBasic版では。

なので、そこら辺をちょっとまとめたいというエントリーです。

それらはpackage的にはcom.sony.jp.felica内にあります。ほかは全部イベントとかなんで、ユーザーが使いたい機能とかはないです。多分。

access()に送るオブジェクトは~Request
それを実行して帰ってくるオブジェクトはResponse
となっており、これらは対になっていると言えます。

で、まぁちょっとまとめてみますと、(ASDoc)から抜粋してみると・・・

FeliCaCloseReaderWriterRequest
FeliCaCloseReaderWriterResponse
FeliCaGetContainerIssueInformationRequest
FeliCaGetContainerIssueInformationResponse
FeliCaOpenReaderWriterAutoRequest
FeliCaOpenReaderWriterAutoResponse
FeliCaPollingAndGetCardInformationRequest
FeliCaPollingAndGetCardInformationResponse
FeliCaSessionRequest
FeliCaSessionResponse
MobileFeliCaRequest
MobileFeliCaResponse
NFCType3TagRequest
NFCType3TagResponse

と、一見沢山あるように見えますが、対になってるのをまとめて、機能だけを列挙してみると

FeliCaCloseReaderWriter
FeliCaGetContainerIssueInformation
FeliCaOpenReaderWriterAuto
FeliCaPollingAndGetCardInformation
FeliCaSession
MobileFeliCa
NFCType3Tag

の7つとなりますね。
んで更に、ユーザーのやりたい処理を扱う上で、必ず必要な命令があるわけで、それが

FeliCaOpenReaderWriterAuto accessのためにオープン
FeliCaCloseReaderWriter  FeliCaへの接続を閉じる
FeliCaSession   他のプログラムに邪魔されないように占有

です。これらもテンプレです。ほぼ絶対必要です。

ということは、実際の機能としてユーザー側が用いるサービスとしては、

FeliCaGetContainerIssueInformation
FeliCaPollingAndGetCardInformation
MobileFeliCa
NFCType3Tag

の4つとなります。

んじゃ、それは何かって話なわけですが。

■FeliCaGetContainerIssueInformation

どうにもそのFeliCa固有の情報(文字列)が入るっぽい感じです。idmのようなFeliCa固有番号とかではなくて製造者や開発者が任意で入れられる情報っぽい。

携帯電話だと機種名とかが入ってるらしいので、機種判別とか、そういうのもありますね。FlashLiteのfscommandのgetDevice的な。これは開発者やデバイスによるので、全てのFeliCaのコンテナ情報に法則があるわけではなさそうです。

つーことは、これをモバイルSuicaとかで使えば、どの携帯の機種でよく使われてるかっていうのが判っちゃうと。判ってどうするものでもないでしょうけど。

■FeliCaPollingAndGetCardInformation

ASDocによると「FeliCaカードの捕捉」らしいです。で、カードを扱うために必要な情報が「システムコード」というらしく、「無償版の時は [FFFF][12FC][80CD]のみ指定可能です。 」と書かれてます。FFとか、なんかワイルドカード設定らしく、FFFFだと全部のカードが反応するらしいです。その領域があるかどうかを調べる感じでしょうかね。

んじゃ実際「12FC」と「80CD」が何かっつーと、判らんです。

これは多分、製造者レベルでしか書き込めない、と思う。

Basic版では、IDmとかPMmとかしか帰ってこないです。

■MobileFeliCa
「携帯電話のフリー領域へアクセス情報を保持するクラス 」らしいです。64Byte程度のフリー領域があるらしくて、そこに書きこんだり読み込んだりできるのだそうな。あとは、docomoの携帯で言えば、iアプリを起動したり、FeliCaが搭載されているモバイル全般だとwebto機能を使ってWebに誘導したり(「接続しますか?」っていう、サイトの一歩手前までの誘導)できるらしいです。

フリー領域は、どういう仕組みになってるのかは不明。パーティションが分けられてるのか。まぁ仕様書読めって話なんですけど。パーティション分けられてなかったら、あんまりおいそれと使えないですねぇ。他のサービスで書き込んだのを上書きすることになるだろうし。

■NFCType3Tag
まぁよく判らんけど、非接触通信の規格らしい?このタグに小容量(最大208Byte)の情報を書き込んだり読み込んだりするためのクラスですかね。コンテストにおけるwonderfl賞の作品がコレを使った作品ですね。

まぁ、知識がないのであんまり詳しくは書けなかったんですが、大体の機能紹介にはなったのかなー。うーん、どうなんでしょうね。

なんか、どかっとテンプレっぽい感じのクラスが出来ないかナー、と模索中。Box2DをQuickBox2Dで扱う的な。

Tags: ,

自分の未熟さに打ちのめされた日

最近、シャワー浴びながら顔を洗ってると、必ず鼻血が出ます・・・。鼻を弄ってるとかそういうのはないんだけどなぁ。突発的に出ることもあるから怖い。幸いにも、会社でまだ出たことはないけど。

今日はAdobe FLASH PLATFORM CAMP Tokyoでございました。非常に疲れました。なんたって、全員レベルが高すぎる!FlashやASの話というよりも、もっと上位のアーティスティックなレベルな方々なので、なんというか、頭が全く追いつかない。いや、とてもすごいなーとは思いましたけどね。

なんというか、FLASHってプログラムでどうこうという小さいものじゃなく、使う人が使えば本当に「自分の作品を扱うためのアーティスト用ツールなんだなー」と思いました。まぁ別にFLASHに限らずでしょうけど。FLASHはグラフィック面が扱いやすいというか、そこに特化したツールだから、そういうアーティスティックなものにはやっぱり向いているんだな、と。

あとはまぁ、もうちょっと会社で率先していろんなことやっていかないといけないなー、とも思いました。ちょっと今の環境に甘え過ぎだよね。

もっとFLASH講師を困らせることをガンガンやって、自分の力をつけていかないと・・・。

とりあえずは、目の前の「ビットの話」と研修の課題と次回プレゼン用の資料と・・・。あと、会社の同僚と組んで何かやろう、うん。

任天堂はWii版『パルテナの鏡』に関して前向き
http://www.kotaku.jp/2010/03/wii_kidikarus.html

【エロ注意】おっぱい丸出し!フジの温泉番組がエロすぎる
http://winzdouga.blog108.fc2.com/blog-entry-980.html
まぁたまにはこんなのも。でもなんか、一時代昔を思い出しますな。昔、志村けんの番組とかでは割と平気で女性が胸を丸出しとか、ドサクサにまぎれた衝撃シーンあったからなー。子供心にドキドキしていたものです。

「死刑廃止派」の千葉法相、半年で執行ゼロ…死刑未執行者数、ついに過去最高の109人に
http://blog.livedoor.jp/newskorea/archives/1177555.html

聖飢魔II、地球デビュー25周年を記念して5年ぶりに全国ツアー
http://www.barks.jp/news/?id=1000059327&ref=rss
写真に長官がいないのが気になる。

拡張現実(AR)ペット「iKat」
http://netafull.net/internet/033877.html

一般永住者が10年で5倍になった理由とは ~彼らが選挙権を獲得したときに何が起こるのか~
http://ameblo.jp/lancer1/entry-10482764118.html

民放ラジオのIPサイマル放送「radiko.jp」スタート
http://slashdot.jp/it/article.pl?sid=10/03/15/083235

セオリー無視!『世界樹の迷宮III』パイレーツ×4編成、明日なき冒険の巻
http://www.gpara.com/pickupnews/news/100312_sq3/
あと少しで発売ですね。

Tags: ,

2010/03/15

ビットを見つめる -intの負数を暴け!-(まとめページ)

先日書いた、

ビット演算で「透明度」の抜き出しでハマったこと
http://melancholy.raindrop.jp/wordpress/?p=1031

に関して、ドエスなFLASH講師から「あれ、問題をスルーしちゃ駄目ですよ」とお叱りを受けたので、ちょっと調べてみました。だいぶ長くなってしまったので、まとめページを作りました。最終的には、上記URLの再構築というか、メソッドの再構築を行います。

正直、自分はここら編の専門的な話はさっぱりなので、もしかしたら間違ってるかもしれません。その時は、優しく教えて頂ければと思います。

あと、指摘してくださったFLASH講師に感謝。

更新履歴:
2010/03/16 00:57 Part3を大分補正、後、少し追記。
2010/03/17 18:32 Part4を追加。
2010/03/18 13:07 Part5を追加。
2010/03/20 20:05 Part6を追加。
2010/03/20 21:09 Part1の内容と流れを少し変更。

目次—————————————————–

■ビットを見つめる Part0 -プラスとマイナスの狭間(モノローグ)-
執筆中

■ビットを見つめる Part1 -intとuintの違いについて-
http://melancholy.raindrop.jp/wordpress/?p=1042

■ビットを見つめる Part2 -立った!最上位ビットが立った!-
http://melancholy.raindrop.jp/wordpress/?p=1054

■ビットを見つめる Part3 -桁を欲すればまず補数を得よ-
http://melancholy.raindrop.jp/wordpress/?p=1072

■ビットを見つめる Part4 -練習は決して裏切らない-
http://melancholy.raindrop.jp/wordpress/?p=1098

■ビットを見つめる Part5 -毎日毎日の足跡がおのずから補数の答えを出す-
http://melancholy.raindrop.jp/wordpress/?p=1105

■ビットを見つめる Part6 -理解・分解・再構築-
http://melancholy.raindrop.jp/wordpress/?p=1114

Tags: ,

ビットを見つめる Part3 -桁を欲すればまず補数を得よ-

さて、前回のお話の続きですが、タイトル通り
「ある数字を、目標の値まで補うための数字『補数』」
を、今回学びたいと思います。

前回、マイナスの値を算出するのが大変でしたが、
これを扱うことによって劇的に計算速度があがります。

実際、前回の考え方だと、とてもマイナスの値は算出できなかったね。
・・・で、補数って何?

最初に書いた通り、「ある数字を、目標の値まで補うための数字」です。
大体の場合は
「n進数において、自然数aの桁を上げるために必要な最低限の数字」
として使われます。

wikipediaによると
「ある基数法において、ある自然数 a に足したとき桁が1つ上がる(桁が1つ増える)数のうち最も小さい数をいう。」
http://ja.wikipedia.org/wiki/%E8%A3%9C%E6%95%B0

らしいですね。

例えば、7(10)に対する補数は10-7で3となります。

ところが、いろんなWebサイトの補数に関する説明を読むと、たまに
「補数=ある数が桁を上げるための最低限の数」
とのみ書いてありますが、
それだけを補数と言ってしまうと、語弊がありますし、混乱の元となります。特に2の補数の話に何故1の補数の話が出るのか、とか、私も大分混乱しました。

なので、ここではちゃんとまとめておきたいと思います。

はーい。

さて、少し難しい話になりますが・・・。

補数というのは、2種類あると考えてください。
1つ目は、「n進数における自然数aの桁を繰り上げるために最低限必要な数」。
これが最初に言った補数の定義ですね。
2つ目は、「n進数における自然数aを現在の桁で最大数にするために必要な数」。

1つめは「基数の補数」、2つ目は「減基数の補数」と言います。
基数は累乗の元となる数字、つまり、X^nにおけるXです。

「基数の補数」は「Xの補数」、「減基数の補数」は「(X-1)の補数」とも言います。

例えば、10進数だったら10が基数になりますね。
上の定義から行くと、基数が10であれば、
「基数の補数」は「10の補数」
「減基数の補数」は「9の補数」
ということです。

例えば、10進法のおける77の「10の補数」は100-77で23。
「9の補数」は99-77で22になります。

その、「補数のネーミング」の意味が判らないんだけど。

例えば、ここでは奇をてらって、5進数を使ってみましょうか。

補数、ということはつまり、「指定する数にするために補う数」ということですね。つまり5進数の「基数の補数」つまり、5の補数は、その桁を5にするために必要な数となります。

しかし、5進数の場合、桁の最大数は5になることはありません。
5を表そうとすると10(5)になりますね。つまり、その桁を5にするということは、桁を一つ上げることにつながります。

だから、5進数における「基数の補数」、つまり「5の補数」とは、
「実際には桁の表示が5になるわけではなく、繰り上げるための補数」
という意味で「5の補数」と便宜的にいっているものと解釈してください。

例えば、5進数における自然数3の「基数の補数」、つまり「5の補数」は
10(5) – 3(5) = 2(5)
ということになりますね。

なるほどー。
あ、つまり、5進数における「減基数の補数」である「4の補数」って、各桁を4にするための補数ってことか!で、実際に4だとその桁の最大になるね!

そう、そのとおり。理解できたようですね。

では、456(10)という数字があるとしましょう。
まず、「基数の補数」は、「n進数による自然数aの桁を繰り上げるために最低限必要な数」でした。
ということは、456(10)における「基数の補数」はどうなるでしょう?

えーと、つまり、今3桁で、繰り上げると4桁、つまり、1000にするために最低限必要な数ってことだよね。
となると、1000-456=544・・・で、10進数ってことは基数が10なんだから、
「456(10)における基数の補数、つまり10の補数は544」!

よく出来ました。
では、「減基数の補数」は?

「減基数の補数」って、現在の桁数で最大数にするための数だよね。
456(10)は3桁。各桁を10進数の桁における最大の数「9」にするのが「減基数の補数」。
つまり「9の補数」だから・・・999-456で543。
だから、「456(10)における9の補数は543」!

正解です。素晴らしい。

ここで、「基数の補数」と「減基数の補数」の関連性について見てみると、
同一の自然数456(10)に対する「10の補数」と「9の補数」の関連性は
544(10) – 1 = 543(10)、つまり「(10の補数)- 1 = (9の補数)」となります。
逆に言うと、(10の補数) = (9の補数) + 1となります。
ここ大事ですから、マークしておいてくださいね。

話が難しくなってきたんだけど・・・。
10進数の補数に関しては、なんとなく判ったかも。

もう少しで本題に入れますので、頑張りましょう。

さて、それでは、ここからは2進数の世界に入りましょう。
ここまでわかれば、「基数の補数」と「減基数の補数」は大丈夫ですね。

それでは、110(2)の「基数の補数」つまり、2の補数はなんでしょう?

んー・・・。110(2)が一桁上に上がる最小の数は・・・。
そもそも、110(2)の一桁上が存在する最低限の数は1000(2)だから、
そこにあがる数を数えればいい、と。

1000(2)は8(10)で、110(2)は6(10)だから、8(10)-6(10)で2(10)を足せばいいんだ。
んじゃ、2進数に直して・・・10(2)が2の補数!

正解です。

ならば、ここからはコンピュータの話になります。
0110(2)の「基数の補数」つまり、2の補数はなんでしょう?

・・・?さっきのと同じじゃないの?0110(2)って110(2)と同じでしょ?

いいところに気付きました。結論から言うと「数値的には同じです」。
十進数に変換すると両方とも6となります。

この違いは、
「現在の桁は何桁」で、
「次の桁は何桁」かです。

よく見てください。0110(2)は、先頭の0を表示しています。
数値として考える場合、この0は省略するっていうのはもう判ってると思います。
しかし、ビットとして考えると、「そこに0というビットが存在している」のです。

前回にもありましたが、intで10110(2)を表現する場合、
無理矢理32ビットに入れるから
00000000000000000000000000010110(2)
になる、という話をしましたね。つまり、この場合も0というビットが存在してるため、桁数は32桁と考えるべきです。

ということは、0110(2)は4桁。110(2)は3桁と考えるべき。
つまり、0110(2)の2の補数を足したときには、結果は
10000(2)でなければなりませんし、110(2)のときは
1000(2)でなければなりません。

つまり、0110(2)の2の補数は
0110(2) + x = 10000(2)
x = 10000(2) – 0110(2)
x = 16(10) – 6(10)
x = 10(10) = 1010(2)

となります。

このように、「ターゲットを何ビットで考えるか」というのが、コンピュータで補数を求める場合に重要になります。

しかし、ぼちぼち計算がややこしくなってきましたね。
というわけで、ここで、補数の求め方に注目してみましょう。

以前に言ったことを思い出してください。
(Xの補数) = ((X-1)の補数) + 1
でしたね。

確かに、例えば500(10)の10の補数と9の補数の違いは、1000にするか、999にするかだったよね。
で、それがどうしたの?

この公式を使うと、簡単に基数の補数が求まるのです。特に2進数は簡単にできます。

2進数の場合は、
(2の補数) = ((2-1)の補数) + 1 = (1の補数) + 1
となりますね。

例えば、今回は8ビットで考えましょう。
00001001(2)の「基数の補数」つまり「2の補数」を求める場合、今まではいちいち10進数になおして考えてましたが、
「2の補数」は「(1の補数) + 1」と同じ、という考え方を使うと楽なのです。

では実際に、00001001(2)の「減基数の補数」つまり「1の補数」を求めてみましょう。

1の補数ということは、2進数において全ての桁が1になるために必要な数でしたね。
ということは、これは00001001(2)を反転させるだけで求めることが出来ます。

実際にやってみましょう。

「00001001(2)」を反転させると
「11110110(2)」になりますね。実際に書いてみてくださいね。

では、実際にこの二つを足してみましょう。全て繰り上がらないので、ものの見事に11111111(2)になりますね。

つまり、11110110(2)は00001001(2)の1の補数であると言えるわけです。

仕組みとしては、各桁の最大数自体が1なので、既に1だったら何も足さなくていいですし、0だったら、1足すだけで限界の値になりますね。

というわけで、反転するだけで、1の補数を求めることが出来ます。

あ、判った!
つまり、「(2の補数) = (1の補数) + 1」なんだから、今求めた1の補数に1を足すことで2の補数が求まる!?

そう!その通りです。
実際に足してみましょう。
11110110(2) + 1は、11110111(2)ですね。
+1をしない段階で00001001(2) + 11110110(2)は11111111(2)になったのですから、
00001001(2) + 11110111(2)は・・・

100000000(2)になる!

・・・あれ?今回8ビットって話だったよね。これだと9ビットになるんだけど。
前回教えてくれたみたいに、数値が溢れたら無視されるの?

お、いいところに目をつけましたね。
そこは後ほどお教えしますので、今は気にしなくていいですよ。
そもそも、なぜ補数を学んでいるかもまだ話してませんしね。

今は、補数を学ぶことに集中してください。

では、もうひとつ、2進数における2の補数を求めてみましょうか。

10100100(2)における「2の補数」を求めてください。

えーっと、まず、反転させることで「(2-1)の補数」つまり、「1の補数」を求めるんだよね。
だから、01011011(2)が1の補数で、そこに1を足すんだから、
「10100100(2)の2の補数」は、01011100(2)!

正解です。もう大丈夫ですね。

さて、数値があふれた場合のお話をしましょうか。
ここからが、「補数を使ってintの負の値を簡単に計算する法則」になります。

やっとここまできたかー!

よく頑張りましたね。あと少しですよ。

さて、結論から言うと、桁あふれは前回と同様、破棄されます。

では、ここから、実際にint型で考えてみましょう。
前回と今回は、「マイナスをどう扱うか」というのが命題ですので、uint型には触れません。
uint型は普通に2進数で扱えますしね。ただし、桁が溢れた場合は、intと同じく下位32ビットより上は無視されることは覚えていておいてください。

さてさて。では、例えば、
10001000101010101010100111010101(2)という数があるとします。当然32ビットです。
最上位ビットは符号なので、マイナスということはわかりますね。
では、これは10進数でどういう数値を表すか解りますか?

解るわけないじゃん!だから今回やってるんでしょ!

いやいや、その通りですね。
さて、そしたら、2進数なので、まずは「2の補数」つまり「基数の補数」を求めてみましょうか。
なぜ2の補数を求めるのかはこれから解りますよ。

では、どうぞ。

んー、10001000101010101010100111010101(2)の2の補数だから、
まずは1の補数を求めて・・・、反転させるだけだから、
01110111010101010101011000101010(2)
で、そこに1を足すことで2の補数になる、と。だから、
01110111010101010101011000101011(2)、だね!

その通りです。

さて、ここで
10001000101010101010100111010101(2)と
01110111010101010101011000101011(2)を足したら?

元の数と2の補数を足すんだから、100000000000000000000000000000000(2)の33ビットになるね。
で、はみ出たら下位32ビットより上は破棄されるから、00000000000000000000000000000000(2)で、0か。

ん?

あ・・・もしかして・・・。

つまり、
10001000101010101010100111010101(2)

01110111010101010101011000101011(2)
が0になるんなら、

0

01110111010101010101011000101011(2)
は、10001000101010101010100111010101(2)になるっていう寸法なわけだね!?

ふむふむ・・・続けて?

(あ、あれ・・・?)
えーっと、んで、01110111010101010101011000101011(2)が・・・・・・・うがーっ!計算が面倒っ!

そんなときは、電卓アプリを使えばいいですよ。
WindowsXPだと、スタート→すべてのプログラム→アクセサリの中に電卓があります。
起動して「表示」から「関数電卓」を選ぶと、関数電卓が使用できます。
そこで2進と書いてあるラジオボタンを選択し、
「01110111010101010101011000101011」
という文字列をCTRL+Cでコピーして、貼り付けると、電卓に入力されます。
先頭の0は自動的に破棄されるので、そのまま入れましょう。
あとは、10進と書いてあるラジオボタンを押すと・・・

あ!10進数に変換された!便利!

えーっと、それで、01110111010101010101011000101011(2)は・・・、2002081323(10)か。
つまり、0-2002081323で、
「10001000101010101010100111010101(2)」は「-2002081323(10)」!

そう、その通りです。(確かめる術がないけど。計算したらこうなったし、大丈夫か。)

やったー!

前回やってた、0からいちいちマイナスしようとしていくよりよっぽど簡単ですよね。

それでは、次は10進数から2進数にしてみましょう。
-100(10)をint型の2進数表示にしてください。

んー・・・。つまり、x + (-100(10)) = 0のxを求めて、そのxの2の補数が-100になるってことだよね。

ということは、xは100(10)になる・・・と。

で、100(10)は・・・、00000000000000000000000001100100(2)だから、これの1の補数を求めて
11111111111111111111111110011011(2)で、そこに1を足すことで2の補数が求められる、と。

ということは、11111111111111111111111110011100(2)が-100(10)!

すばらしい!よくできましたね。

さて、極論を言うと、「コンピュータの2進数における2の補数とは、足して0に導くための補数」というわけです。
つまり、現在の値と正反対の値を足すことによって、0になるわけですから、
コンピュータ上での6(10)における2の補数は-6(10)、-8(10)における2の補数は8(10)となります。

以上のことを解ったうえで扱うと、このように、
「マイナスの値がどのように収められているのか」
が解ります。

・・・ところで、マイナスがどうやって格納されてるのかっていうのは、前回と今回で解ったのだけど、
これを使ってどうこうすることってあるの?

普通にASを扱う分には全くもって無いと言っていいと思います。

が、しかし、色分解では必ずビット演算が必要ですし、
色を構成するのにもビット演算が必要になります。

まぁ・・・、今回のような「マイナスを算出する」必然性というのはあまりない気がしますが、
知っておくにこしたことはない、という感じでしょうか。

今回のボリューム、かなりのものだと思うけど、無駄だった、と?

いや、だから、無駄ではないんですがね。

とりあえず色分解や構築であれば、前回のことさえ解っていれば、とりあえずは大丈夫ですよ。
それでは、次回は、実際に色分解と構築をやってみましょうか。

できれば最初からそれやってほしかったけどね!

やれやれ、ふてくされてしまいましたか・・・。

さて、では、とりあえず今回の補足をしておきましょう。
今回は、2の補数を使って負の値、あるいは2進数表記を算出したわけですが、
何故2の補数を使うと、負の値を算出できるのでしょう?

・・・そういう風にintが構成されてるからじゃないの?

おお、若干投げやり気味ですが、いい答えですね。まさにそういうことです。
int型は、2の補数を利用しての負の値の構成をしているので、同様に2の補数を使ってマイナスを算出できるのです。
当たり前といえば、当たり前ですね。

しかしながら、世の中には、そのような方法ばかりで負の値を構成してるわけではなかったりするのです。
詳しくは、こちら(符号付数値表現)を見て欲しいのですが、
パッと見、4つの方法がありますね。その中に2の補数もあります。

以前、あなたが答えた解答にマイナスゼロという解答がありましたが、
実は、この中の「1の補数」という仕組みの中に、それはあるのです。
実際に、そういう仕組を組み込まれているものがあるということですね。

但し、intはそういう仕組を取ってないので、ハズレではあるんですが。

・・・もういいから、少し休ませてー・・・。

だいぶ疲れてますね。まぁ、今回はかなりのボリュームになってしまったので、
もし余力があれば、ゆっくりと何回か読まれることをお勧めしますよ。

なにぶん、自分も大して判っては・・・ゲフンゲフン。

何か言った?

いえいえ、何も。

そんなわけで、『Part4 -練習は決して裏切らない-』をご期待下さい。

Tags: ,

今週もはじまりました。

WILLCOM 『月額1,450円で音声通話もデータ通信も使い放題』
http://willcom.bg.cat-v.ne.jp/article/887311.html
機種代が高いかと思ったけど、2年契約で買えば安くつくな。2年間は月々1480+1450円程度で、それ以降は1450円で、このサービスか。今使ってるPHPの基本料金と変わらんなー・・・。これは変え時なのかな。

ただ、これJASON氏が使ってるの見たけど、動作がめっちゃモッサリだったんだよな・・・。

外務省が朝鮮人の戦時徴用は245人と発表 ~既出だが大きな意義のある発表~
http://ameblo.jp/lancer1/entry-10479962207.html

アガり症のプレゼンターさん必読、「聴衆はアナタ自身を注目しているわけではない」
http://www.lifehacker.jp/2010/03/100308better_presentations.html

アドビとクラスメソッドが開発者向けセミナー「Flash Builder 4を用いた高品質RIA開発セミナー」3月24日開催
http://web-tan.forum.impressrd.jp/n/2010/03/11/7556
行くか行くまいか・・・。

PCに隠したエロ画像を根こそぎ暴く「探偵ドライブ」登場…夫や子供の隠しエロ画像が次々と明らかに
http://blog.livedoor.jp/dqnplus/archives/1438686.html
やめて!

職業選びで悩めるのがうれしい『世界樹の迷宮III 星海の来訪者』【前編】
http://www.famitsu.com/game/news/1232889_1124.html?ref=rss

「ズブ濡れになった本は凍らせると復活する」というハック術
http://www.lifehacker.jp/2010/03/post_1423.html

民主党「県外だー」社民「国外だー」 →アメリカ「もう普天間でいいわ・・・」 最悪のシナリオへ
http://alfalfalfa.com/archives/388957.html

「もしもし警察?!プリウスのアクセルが戻らない助けて!」 ← 米メディアがでっちあげと報道
http://alfalfalfa.com/archives/388949.html

ファルコムの新作は『空の軌跡』と『イース』のキャラが入り乱れる対戦ACT!!
http://news.dengeki.com/elem/000/000/245/245436/
>7月29日に発売する。

コードギアス史上、最大の衝撃イベント「コードギアス 反逆のルルーシュ キセキの誕生日」Blu-ray&DVD&UMDで発売決定!
http://hobby-channel.net/dvdcd/18416-18416.html

[GDC 2010]FF13はなぜ“一本道”なのか。ディレクターの鳥山氏自らそのゲームデザインについて語った「The Crystal Myth and FFXIII」をレポート
http://www.4gamer.net/games/050/G005070/20100313019/

Tags: ,

2010/03/14

ビットを見つめる Part2 -立った!最上位ビットが立った!-

10000000000000000000000000000000(2)
から
11111111111111111111111111111111(2)
までが
intの負の数、
そしてuintの2,147,483,648~4,294,967,295であると話しました。

今回は「どうやってマイナスを処理するのか」のお話をしたいと思います。
uintは普通に2進数で考えられますが、intだとどう格納されているのか、ということです。

では質問です。
10000000000000000000000000000001(2)はintでなんでしょう?

ちなみに、今回書く2進数の長い列は、32個固定なので、
数える必要はないです。違う場合はその都度通知します。

んー。思うに、最上位ビットが符号を表してると思うんだよね。

ほう。

ということは、符号とその後ろを分割して考えればいいと思う。

だから、最上位ビットが1だからマイナスで、その後ろは
0000000000000000000000000000001だから、-1(10)!

なるほど。考えましたね。

では、次の質問です。

(あれ?間違ってた・・・?)

10000000000000000000000000000000(2)はなんでしょう?

え?あ・・・うーん・・・。
・・・・・・-0?

つまり、00000000000000000000000000000000(2)は+0?

うん・・・。

数学的にはもしかしたら違いはあるのかもしれませんが、
今回はそういう発想はなしで。つまりハズレです。

んー・・・お手上げだよ・・・。

解説をする前に、まず解答を。
10000000000000000000000000000001(2)は-2,147,483,647、
10000000000000000000000000000000(2)は-2,147,483,648です。

私、ビット演算やめます。理解不能です。

まぁまぁ。もうちょい待って。

では、-1はどう表記するか。
正解は、11111111111111111111111111111111(2)です。

全部1なのに-1なの?!

一見不思議ですが、あることを理解すれば納得が行くと思いますよ。

あること?

それは、コンピュータの数値管理に関することです。
例えば、11は2進数でどう書きますか?

1011(2)!

ですね。では、コンピュータはどうやってそれを保管するでしょう。

今までの書き方から言って、00000000000000000000000000001011(2)かな?

その通りです。
つまり、コンピュータは「無理矢理」32個のビットとして保管します。

では、次の質問です。
これはコンピュータではなく、純粋に2進数で考えてください。
11111111111111111111111111111111(2)。これは4294967295ですね。
では、これに1を足した場合。2進数、10進数、それぞれどうなるでしょう?

えーっと、普通に考えていいんだよね。

2進数は、全部繰り上がるから、

100000000000000000000000000000000(2) ←33ケタ
10進数は
4294967295+1で4294967296

・・・でいいんだよね・・・?

正解です。そんなにビクビクしなくていいですよ。
それでは、これをコンピュータの世界で考えます。
これらは、intとuintで、それぞれどうやって表記されるでしょう?

・・・え・・・?
だって、intもuintも32ビットでしょ?

100000000000000000000000000000000(2)は33ケタだからオーバーしてるよ?
エラーがでるんじゃないの?

すばらしい、いい答えです。答えは違いますが。

(イヤミな感じだなー・・・)

思い出していただきたいのですが、先に書いたとおり、
コンピュータは「無理矢理」32個のビットとして保管します。
これは、はみ出たときにも適用されます。

はみ出た場合は、下位32ビットより上は消去されます。
これは何度も書いたとおり、数値は無理矢理32ビットに収められるためです。

つまり、どういうことになるでしょう?

ということは、
00000000000000000000000000000000(2)っていうことだから・・・。
答えは0!

そう、その通り。当然この場合は10進法的にも0になります。

さて、これはつまり、コンピュータ的には、
32ビットがフルに1で埋まってるときに1を足すと0に戻ることを表します。
ループするんですね。

では、次の質問です。

この00000000000000000000000000000000(2)から
1を引くとどうなるでしょう?

あ、もしかして、さっき11111111111111111111111111111111(2)に1を足したら0になったんだから、00000000000000000000000000000000(2)から1を引いたら元に戻る!?

つまり、00000000000000000000000000000000(2)-1は0-1で、
11111111111111111111111111111111(2)で、-1になるってこと?!

正解です!すばらしい。
これで流れ的には掴めた感じですね。

では問題です。-2はどう書くでしょう?

11111111111111111111111111111111(2)から1を引くだけだよね。

ということは、11111111111111111111111111111110(2)!

正解です。では、-527はなんでしょう?

え、あれ?えーっと、えーっと・・・。。

難しいですよね。判ってて質問したので、落ち込むことはないですよ。
こんな問題、私も願い下げです。

意地悪!

はいはい。さて、これで考え方自体は分かっていただけたと思います。
では、次回は、こういう問題を簡単に解く計算式をお伝えします。

・・・そんな計算式あるなら最初に教えてくれればいいのに・・・。

おっと、そんな目で見ないでください。
今回はあくまで、その考え方を知ってほしかったのです。
いきなり計算式を教えてもいいのですが、その方法自体はどこにでも
ありふれてます。
また、丸暗記ということは応用が利かないことでもあります。

今回の話を理解できれば、次回はかなり楽に理解できると思いますよ。

さて、今回の補足ですが、intの最小値、つまりint.MIN_VALUEは-2147483648です。
これはつまり10000000000000000000000000000000(2)ですが、
そこから1引いて-2147483649を表そうとするとどうなるでしょう?

今回の解説からいくと・・・。
最小値の-2147483648は、10000000000000000000000000000000(2)なんだよね。
で、マイナスする場合は、一つ引くんだから、
01111111111111111111111111111111(2)になるわけで。
でも、これってint.MAX_VALUEと同じだよね?
ということは、最小値が、一転して最大になってしまう?

そうです。int.MIN_VALUEはint.MAX_VALUEに隣接しているのです。
図で表すとこうなります。(稚拙なのは勘弁してください)

左側が0(2)で2進数がどんどん増えていくごとに、数値も増えていきますが、
2^31-1、つまり01111111111111111111111111111111(2)が
2^31、つまり10000000000000000000000000000000(2)になった時、
数値はいきなり最小値になってしまいます。

普通にプログラム上で計算する場合、このようなことは考えなくてもいいですが、
ビットを直接扱って数値を構築しようとした場合、この知識は必要不可欠です。

というわけで、次回、Part3 -桁を欲すればまず補数を得よ-をご期待ください。

Tags: ,