コグノスケ


link 未来から過去へ表示(*)  link 過去から未来へ表示

link もっと前
2008年5月3日 >>> 2008年5月3日
link もっと後

2008年5月3日

何を補うの?

毎回話題がバラバラな日記ですみません。今日は補数の話です。

N進数の補数は2つあります。Nの補数と、N-1の補数です。10進数ならば10の補数と10-1の補数(9の補数ともいう)があります。

N進数における二つの補数

あるN進数xの Nの補数yとは、足すと桁上がりする最小の数値を指します。
10進数でいきますと、x = 123だとしたら、10の補数は足すと桁上がり(1,000になる)する最小の数値ですから877です。

要するにy = 1,000 - x = 1,000 - 123 = 877と計算します。4桁の数字なら10,000から引けばいいですし、5桁なら100,000から、n桁なら10^(n) から引いてください。

あるN進数xの N-1の補数zとは、足しても桁上がりしない最大の数値を指します。
また10進数を例に取ると、x = 123として、10-1の補数は足しても桁上がり(1,000)に達しない最大の数ですから、876です。足すと999になります。

これも要するにz = (1,000 - 1) - x = 999 - x = 876と計算します。特徴として、10の補数から1引いても得られますし、逆に10-1の補数に1を加えると10の補数になります(この性質は後ほど重要です)。

補数の活用方法

Nの補数は何が嬉しいかというと「負の数の表現として使えば、引き算が不要になる」という点です。

3桁の10進数500 - 300を計算したいとします。「引き算は知らないが3桁の足し算と10の補数を書いた表だけ持ってる」と仮定します。むちゃくちゃに見えますけど、後で意味が分かると思います。

引き算は知りませんので、まずは負の数を消しにかかります。負の数は絶対値の補数に置き換えて消します。表を見ると300の10の補数は700(計算で出すなら1,000 - 300)ですから、
500 - 300 = 500 + 700
こう置き換えます。すると足し算のみになって、計算できるようになります。
500 + 700 = 1,200
4桁目が出てきてしまいましたが、3桁の足し算しか知らんので4桁目は捨てます。さようなら〜。
1,200 => 200
この結果は500 - 300 = 200の結果と一致します。

不思議に見えますが、そもそも補数yの定義がy = 1,000 - xなので、x = 300で式を展開すると、
500 + (1,000 - 300) = 1,200 --(4桁目無視)--> 200
となるのは当たり前といわれれば当たり前の結果です。しつこいですが大事なポイントは「引き算が足し算に化ける」という点です。

2進数だと非常に嬉しい

とはいえ、10進数だと補数を計算するために結局引き算が必要で、ありがたみがありません。これはその他の記数法(図では3進数を例とした)でも同じです。


3進数と3の補数、3-1の補数

ところが2進数となると非常に嬉しい性質があります。以下の図を見てください。


2進数と2の補数、2-1の補数

2進数においては全桁を反転させる演算(Not演算)によって、容易に2-1の補数を得ることができ、そこに1加えれば2の補数を得ることができます。つまりNot演算さえあれば2の補数の導出に引き算は不要です。コンピュータだからこそできる技といえましょう。

この性質のためコンピュータに減算器は不要で(※)、加算器の前にNot演算と1加える回路をつけるだけで良いのです。回路が少なくなればコンピュータも安くなります。いやあ、補数って素晴らしいですね。

(※)コンピュータは前章の説明に出てきた「引き算は知らないが3桁の足し算と10の補数を書いた表だけ持ってる」の代表格です。コンピュータの場合2進数を扱うため10の補数ではなく2の補数です。
まとめると「一定桁(32桁、64桁など)の足し算と、2の補数しか知らない」変な奴と言えます。本当は意図的にそう作っていると言った方が正しいですけど…。

負の数を解釈

補数を負の数として扱うと良いこと(減算がなくなる)があるのは分かっていただけたかとおもいます。残る問題はどこからを負の数と見なすかです。卑近な例で言うとprintfしたときに、どこからマイナスなのよ?って話です。

前章まで話してきた計算の問題と関係ありそうに見えますが、実は全然関係ありません。ぶっちゃけた話、どこから負の数と見なしても構いません。以下の図をご覧下さい。


2進数から10進数へ解釈する一方法

この図にある解釈方法ですと2進数の101以上を負の数と見なします。

  • 101未満の数を表示しなさいと言われたら、そのまま10進数に変換した値を印字します。
  • 101以上の数を表示しなさいと言われたら、補数をとって10進数に変換した値と、マイナスの符号をともに印字します。
例えば110を渡されたら、101以上なので補数を取って010とし、010を10進数にすると3なので、-3と表示します。

何?ずれてる?いやいや…。このような解釈でも使っている人がウンと言えばそれで良いんです。とはいったものの、この方式ではウンと言う人は少なそうです。この方式は欠点が多すぎます。

桁が増えたときに正負の境界をどう決めるかがあいまいであるがために、境界を見分ける処理が複雑になる可能性があります。プログラマや回路設計者に嫌われますね。それとやたら正の数ばかりが多くて、負の数を使いたい人にも嫌われます。

良い解釈方法はあるか

多くの方が見慣れたパターンは、最上位のビットが1なら負の数と見なす、以下のような解釈方法でしょう。


2進数から10進数へ解釈する効率的な方法

この解釈方法が採用されている理由は、効率的だからだと思われます。この解釈方法であれば、何桁になろうとも「最上位ビットの有無」という同じルールが適用できます。さらに正の数の範囲と負の数の範囲がほぼ同じ(負の数の範囲が1広いけど)で使いやすいのです。

編集者:すずき(2008/05/04 16:51)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link もっと前
2008年5月3日 >>> 2008年5月3日
link もっと後

管理用メニュー

link 記事を新規作成

<2008>
<<<05>>>
----123
45678910
11121314151617
18192021222324
25262728293031

最近のコメント20件

  • link 20年6月19日
    すずきさん (04/06 22:54)
    「ディレクトリを予め作成しておけば良いです...」
  • link 20年6月19日
    斎藤さん (04/06 16:25)
    「「Preferencesというメニューか...」
  • link 21年3月13日
    すずきさん (03/05 15:13)
    「あー、このプログラムがまずいんですね。ご...」
  • link 21年3月13日
    emkさん (03/05 12:44)
    「キャストでvolatileを外してアクセ...」
  • link 24年1月24日
    すずきさん (02/19 18:37)
    「簡単にできる方法はPowerShellの...」
  • link 24年1月24日
    KKKさん (02/19 02:30)
    「追伸です。\nネットで調べたらマイクロソ...」
  • link 24年1月24日
    KKKさん (02/19 02:25)
    「私もエラーで困ってます\n手動での回復パ...」
  • link 24年1月24日
    すずきさん (02/13 11:48)
    「ありがとうございます。\n私のPCはもう...」
  • link 24年1月24日
    えはらさん (02/12 15:00)
    「Powershellのスクリプトは以下の...」
  • link 24年2月2日
    すずきさん (02/02 18:17)
    「サーバー側の設定はとても簡単でした。ちょ...」
  • link 24年2月2日
    hdkさん (02/02 08:54)
    「さくらのレンタルサーバの設定でLet's...」
  • link 24年1月24日
    すずきさん (01/28 11:35)
    「ご指摘ありがとうございます。確かに間違っ...」
  • link 24年1月24日
    通りすがりさん (01/27 14:05)
    「Powershellで解決しなかったのは...」
  • link 23年11月29日
    すずきさん (12/04 00:38)
    「あ、そうか。1nsですね。ありがとうござ...」
  • link 23年11月29日
    hdkさん (12/03 18:49)
    「>(本来1usなのに1msになって...」
  • link 23年11月29日
    すずきさん (12/03 00:35)
    「大山先生、お久しぶりです。コメントありが...」
  • link 23年11月29日
    大山恵弘さん (12/02 18:53)
    「すずきさんのX(旧Twitter)へのポ...」
  • link 20年7月12日
    すずきさん (10/19 11:17)
    「ご指摘ありがとうございます。9月の編集は...」
  • link 20年7月12日
    通り縋りさん (10/18 19:08)
    「上の記事2023年9月編集という事ですが...」
  • link 23年9月22日
    すずきさん (09/23 21:14)
    「そうなんですよ。賢いなーと思って自分でも...」

最近の記事3件

  • link 24年4月17日
    すずき (04/18 22:44)
    「[VSCodeとMarkdownとPlantUMLのローカルサーバー] 目次: LinuxVSCodeのPlantUML Ex...」
  • link 23年4月10日
    すずき (04/18 22:30)
    「[Linux - まとめリンク] 目次: Linuxカーネル、ドライバ関連。Linuxのstruct pageって何?Linu...」
  • link 20年2月22日
    すずき (04/17 02:22)
    「[Zephyr - まとめリンク] 目次: Zephyr導入、ブート周りHello! Zephyr OS!!Hello! Ze...」
link もっとみる

こんてんつ

open/close wiki
open/close Linux JM
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 2020年
open/close 2021年
open/close 2022年
open/close 2023年
open/close 2024年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDFファイル RSS 1.0

最終更新: 04/18 22:44