* 符号付き整数について
-(by [[K]], 2013.06.24)
** (0) はじめに
-rev2でbitが出てくるようになり、この辺の挙動への知識があったほうが、VMなどの開発に有利なので解説することにしました。
-アプリ開発しかしないときは、この知識はなくても大丈夫です。というかVM開発でも細かいことを気にしなければ、この知識はなくても大丈夫です。

** (1) 10進数で練習(足し算、引き算、掛け算)
-ここにゼロもしくはプラスの数しか計算できない、しかも2桁しか表示できない、超おんぼろの計算機があったとしましょう。
--「01」+「23」=「24」
--こんな感じです。
-さてこの計算機で、「97」+「05」を計算したらどうなるでしょうか。
--「97」+「05」=「02」
-おお、なんと2になってしまいました。そうです、本当は102なのですが、二桁しか表示できないので、「02」になってしまうのです。
-これを「桁が足りなくて不十分な結果を表示している(=エラー)」とはあえて考えないで、5にある数を足したら2になった、と考えてみると、「97」は-3の代わりになっていると考えることができます。
-負の数が計算できないおんぼろ計算機でしたが、こうやって工夫することで、マイナスの数が扱えるのです。
--「99」は-1の代わり。
--「87」は-13の代わり。
--「65」は-35の代わり。
----
-さてこの「代用」はどのくらい有効なのでしょうか。試しに、「87」と「99」を足してみましょう。
--「87」+「99」=「86」(本当は186)
-ほほう、(-13)+(-1)=(-14)なので、この計算は合っています。つまり、負の数どうしを加えてもうまくいくのです。
-じゃあ引き算はどうでしょうか。-2から3を引いてみましょう。
--「98」-「03」=「95」
-これは-5なので合っています。
-では、-2から-3を引くのはどうでしょうか。
--「98」-「97」=「01」
-すごいじゃないですか。ばっちりですよ!
-さらに悪乗りして、(-3)*3をやってみましょう。
--「97」*「03」=「91」(本当は291)
-「91」は-9なのでこれもあっています。
-じゃあ、(-4)*(-5)は?
--「96」*「95」=「20」(本当は9120)
-おおー。これもあっていますね!!
-でもうまくいくのはここまでです。割り算はうまくいきません。だから検算もしません。
----
-引き算で「01」から「07」を引いたらどうなるでしょうか。おんぼろ計算機ではもちろんエラーです。エラーなのですが、とりあえず無理やり「94」が表示されます。
-この表示の根拠はこうです:
--1から7は引けない。でももしかしたら1は1ではなくて101のつもりだったのかもしれない。
--ボクは2桁しか入力できない計算機だから、ご主人様は101を入力したかったけど下2桁で我慢したのかもしれない、うん、きっとそうだ。
--1から7は引けないけど、101からなら引ける。ご主人様の単なるミスかもしれないからエラー表示はするけど、でも一応101から7を引いた94も表示しておこう!
-そしてこの「気の利いた対応」のおかげで、1-7=(-6)となり、符号付き整数の考え方はうまくいくことになります。
----
-すこしテクニックを紹介しましょう。ある数があったとして、その数の符号を反転したいとします(つまり-1を掛け算するということです)。その時は以下の手順でできます。
--「99」からその数を引く。・・・これは繰り下がりのない引き算になるので超簡単。暗算もできる。
--その結果に「01」を足す。
-つまり、「12」の符号を反転したければ、99-12=87にして、+1して「88」というわけです。
-「56」の符号を反転すると、43+1=「44」というわけです。
-まあそんなことしなくても、100から引けばいいって?まあそうです。でも10進数以外では引き算の暗算は容易ではないので、繰り下がりのない引き算形式を経由する方法は、役に立つことがあります。
----
-この符号付き整数では、最初の桁が「0~4」の場合は正の数、最初の桁が「5~9」の場合は負の数、と解釈します。

** (2) 符号拡張(まだ10進数だけで考えています)
-この2桁のおんぼろ計算機ですが、もしもう一台4桁のおんぼろ計算機があったとしたら、数値がどのように対応するでしょうか。
--「00」=「0000」
--「12」=「0012」
--「34」=「0034」
--「98」=「9998」(どちらも-2を意味する)
--「76」=「9976」(どちらも-24を意味する)
--「54」=「9954」(どちらも-46を意味する)
-このように、補う上位2桁は、「00」だったり「99」になったりします。どちらになるかは、十のくらいが「0~4」か「5~9」なのか、ということで決まります。
-ちなみに符号なし整数では、かならず「00」を補います。これはゼロ拡張と呼ばれます。それに対して、値によって「99」だったり「00」だったりする桁拡張は「符号拡張」と呼ばれます。

** (3) 計算の省略(まだ10進数だけで考えています)
-たとえば歴史上の人物の享年(死んだ時の年齢)を調べる計算を考えます。
-たとえば織田信長は、1534年に生まれて1582年に死亡しています。
-このとき1582-1534をまじめに計算することもできますが、100歳未満だということを事前に知っていれば、下2桁だけで計算することもできます。「82」-「34」=「48」。
-この方法は世紀をまたがっても問題なくできます。徳川家康なら1616-1543ですが「16」-「43」=「73」で、ちゃんと正しい答えが出るのです。
-上位の桁がそろっているからそんなことができるんだ、と思うかもしれません。じゃあ、1から(-1)を引くことを考えましょう。答えは2になるべきです。
--4桁でやった場合:「0001」-「9999」=「0002」(10000を補うルールを使いました)
--2桁でやった場合:「01」-「99」=「02」(100を補うルールを使いました)
--1桁でやった場合:「1」-「9」=「2」(10を補うルールを使いました)
-つまり、結果の範囲がだいたいわかっていれば、その桁数だけ取り出して、それより上の桁を全部無視しても、正しい答えが出るのです。
-これは引き算だけではなく、掛け算でも足し算でも同じ性質があります。

** (4) ゴミの除去(まだ10進数だけで考えています)
-4桁くらいの数値を10個合計し、25で割った余りがいくつになるのか知りたいとします。この時、計算をまじめにやる必要はなく、合計の際は2桁だけやっていれば十分でしょう。
-しかし計算機の都合で、4桁のまま計算してしまいました(わざわざ2桁だけを取り出す操作が面倒だったので)。さてその結果は「6543」でした。・・・ここで問題です、もしこの計算を上記の考察のとおり2桁の計算機でやっていたら、どんな結果になっていたでしょうか。そうです、「43」です。これを4桁の計算機のままで表現するのなら「0043」になります。
-この「0043」はどうすれば得られるでしょうか。そうです、上位の桁(=ゴミ)を0でつぶしてしまえばいいのです。
-符号付き整数では、ゼロ拡張ではなく符号拡張するべきなので、「6543」の「4」をみて「00」を埋めることになります。

** (5) 2進数
-上記の議論はすべて2進数でもそのまま成立します。そしてそれが、OSECPU-VMの命令セットの根拠になっています。


* こめんと欄
#comment

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS