技術者向けでは基本的すぎて笑われてしまうかも知れません。が、プロの方で詳しい方にお聞きしたかったのです。例えば、プラスの数値を算術右シフトすれば
「あふれたビットを破棄するのは、その範囲で表現できないから切り捨てる。
たとえば3を2で割ると1.5ですが、
1右シフトすると1になりますが、
0.5を保持する桁がないからですね。
逆に桁あふれも同じ意味ですね。」という回答を見たのですが、確かにプラス部(負数でない部分)については理解出来るのですが、これがマイナスの整数(電算機上では負数)の場合、例えば「-1.5」であれば「-2」になるということでした。なぜ単純に「-0.5」部分の切り捨てで済まないのでしょうか?

このQ&Aに関連する最新のQ&A

A 回答 (5件)

No.1です。



>どうしても分からないのは、(中略)つまり絶対値で0.5の差が出る理由です。
くどくなりますが、すべては『2の補数を使用するから』というところに集約します。

以下は4bitで説明します。
4bitの場合、表せる範囲は「0000」~「1111」の16種類です。
正負の数を「1の補数」で表現した場合
 0000:0   1111:0(本来は使用しないが扱い上は0)
 0001:+1  1110:-1
 0010:+2  1101:-2
 0011:+3  1100:-3
 0100:+4  1011:-4
 0101:+5  1010:-5
 0110:+6  1001:-6
 0111:+7  1000:-7
となります。「-7~0~+7」までの「15」の数値を表します。
対して「2の補数」は
 0000:0   1111:-1
 0001:+1  1110:-2
 0010:+2  1101:-3
 0011:+3  1100:-4
 0100:+4  1011:-5
 0101:+5  1010:-6
 0110:+6  1001:-7
 0111:+7  1000:-8
となります。「-8~0~7」までの「16」の数値を表します。
つまり、+(0も含む)と-で表現できる範囲が1つずれているのです。

あえて誤解するように書けば、「0」が中心ではなく「-0.5」がデータ的な中心です。
絶対値は、データの中心である「-0.5からの相対位置」になりますから「+1」の絶対値なら「1.5」、「-1」の絶対値は「0.5」、絶対値の差は「1」となります。
この値を「プラスとマイナスだから/2」とすると「0.5」になります。
それによって発生する問題です。

正直なところ、なんとか理屈づけて納得しようとしても難しいので「こういうものだ」と割り切ったほうがいいと思います。
    • good
    • 0
この回答へのお礼

ほんとうにご丁寧に分かりやすい解説有難うございました。SilverThaw
様の親切さにただ感涙するのみです。感謝いたします。

お礼日時:2009/05/22 20:50

No.1です。


>(1)n進数の補数にnの補数とn-1の補数の二つがある理由が分かりません。
正直、私も知りたいです。
このおかげで私も過去に「2の補数」のつもりで作っていたら、実は「1の補数」でイタイ目を見たことがありますので(単に、仕様の確認漏れだけなのですが)
個人的な考えですが、
・単純にわかりやすくビットを反転しただけ(+1の処理がいらない、回路も小さくなる)
・「0000 0000」を起点として「0000 0001」「0000 0010」……と、「1111 1111」「1111 1110」……と進んでいくのがわかりやすいから
ではないかと考えたりしてますが。

>(2)一番分からないのは、このシステムで100を2進数で8ビットで表したものを(後略)
結論から書くと「10進数」ではなく「2進数(2の補数表現)」で処理しているためです。
単純に10進数で算出した際の小数点を切り捨てているわけではありません。
「2進数(2の補数)」で考えるとすっきりします。

今までと同じく8bit表現で記載します。
「+100」は「0110 0100」、「-100」は「2の補数」では「1001 1100」で表されます(算出方法はNo.3参照)。
これを「右に3ビット算術シフトする」と
「0110 0.100」(+100)は「0000 1100」=「12」
「1001 1.100」(-100)は「1111 0011」
となります(上記はわかりやすくするために、シフトした際に一番下位のbitの位置に「.」をつけています)。
この「1111 0011」は「1111 1111」(-1)から数えて13番目であり「-13」となります。
(尚、マイナス値からの絶対値を求める場合も、「bitを反転して+1」は同じです。)

この回答への補足

ご丁寧に毎回詳しいご回答を本当に有難うございます。ただ悲しいですけど、自分には向かないのか・・・どうしても分からないのは、(1)+100を2進数で8ビットで表したものを右に3ビット算術シフトする場合は+12になり(2)-100を同じように処理した場合、-13になる、つまり絶対値で0.5の差が出る理由です。甘えすぎかも知れませんが、もし、可能でしたら、是非ご教授下さい。

補足日時:2009/05/22 18:33
    • good
    • 0

No.1です。



>(前略)(残ったビットを10進数表示した場合の絶対値が、正負でことなる理由が分からないのです)もしよろしければご教授願います。
結論から書くと「マイナス値を表す手法が『2の補数』基準」で考えているからです。

まず、「2進数」は理解されていますか?
また、「マイナスを表すための方法」については?
ここが理解できていないと難しいです。

以下は8bitの2進数で説明します。
10進数の「+3」は2進数では「0000 0011」と表します。
これを右に1bitシフトすれば「0000 0001」となります。
一番下位ののbitが追い出されるため、結果は「1」となります。

対して「-3」は「2の補数」で表すと「1111 1101」となります。
「2の補数」はマイナス値を表す方法の一つで、正の値のbitの0/1を逆転した値「+1」することで値を表します。
これにより、マイナス値の場合は必ず最上値のbitが「1」になります。
「-3」の場合は「0000 0011」をbit反転して「1111 1100」、それに「+1」して「1111 1101」となります。
この値を右に右に1bitシフトすれば、桁あふれし「1111 1110」となります。
「2の補数では」この値は「-2」です。

ちなみに、マイナス値の手法には「1の補数」というものも存在します。
この場合「-3」の値は「1111 1100」。
右に1bitシフトした値は「1111 1110」となり、結果は「-1」となります。

この回答への補足

ご丁寧に詳しい補足説明有難うございます。確かにまだ理解が曖昧な部分あると思います。もし更に教えていただけるなら(1)n進数の補数にnの補数とn-1の補数の二つがある理由が分かりません。(2)一番分からないのは、このシステムで100を2進数で8ビットで表したものを右に3ビット算術シフトする場合と-100をこの補数表現で同様の行為(右に3ビット算術シフトする)を行った場合とで+と-の符号を除いた絶対値に違いが出ることです。前者は10進数表記では12.5から小数点以下の0.5(2進小数点以下の1ビット)を切り捨て、12?後者もやはりこの算術シフトによる右の桁の切り捨てで小数点以下のビットは消えるはずなのに-13?(絶対値13)?+と-では0と1は反転するのは分かるのですが、この計算結果になるロジックが分からないのです?

補足日時:2009/05/21 21:59
    • good
    • 0

「負の数の丸め」は表現として微妙なところがあります.


たとえば「-1.5 を整数に丸める」ときに「-2 とする」のか「-1 とする」のかという選択があります. 実際には正の場合にも選択肢が考えられます. ということで, 丸めの方法には
・負の無限大への丸め (小さい方に丸める)
・正の無限大への丸め (大きい方に丸める)
・0 への丸め (絶対値の小さい方に丸める)
・最近値への丸め (最も近い値に丸める: 中間のときは偶数にするのがきっと正しい)
などがあります.
今の場合は「負の無限大への丸め」となるので -1.5 が -2 になります.
解釈によっては「-1.5 を -2 にするのは -0.5 の部分を切り捨てたんだ」とも見なせますけどね.

この回答への補足

すみません。丸めというよりは単純に算術右シフトした場合に、小数点以下にあたるのビットを切り捨てねばならない場合のことです。

補足日時:2009/05/21 19:17
    • good
    • 0

「(-3)÷2」とした場合、8bitでの-3の「2の補数」は2進数で表すと「1111 1101」。


「2で割る」ことにより、右に1bitシフトした値は「1111 1110」。
これは「-2」にあたるから。

この回答への補足

早速のご回答有難うございます。ただ小数点以下を表示しないビット列で右算術シフトした場合でビットが一つ溢れた場合、プラス部なら0.5にあたるビットの切り捨てとかで理解出来るのですけれども、負数で
はなぜ単純に-0.5に当たるビットの切り捨てとならないのでしょうか?(残ったビットを10進数表示した場合の絶対値が、正負でことなる理由が分からないのです)もしよろしければご教授願います。

補足日時:2009/05/21 19:08
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QIPアドレスを十進数から二進数に直す計算式

こんにちは。初級シスアドの勉強を最近始めた者です。
2進数を10進数に変換する方法はわかったのですが、10進数から2進数に変換する計算の仕方がわかりません。

例えば
200.170.70.16→
11001000 10101010 01000110 00010000

どうしてこのようになるのか教えてください。
数学がまるでダメなもので苦労してます。。。
よろしくお願いいたします!

Aベストアンサー

200をどんどん2で割っていってみましょう

200/2=100・・・0
100/2=50・・・・0
50/2=25・・・・0
25/2=12・・・・1
12/2=6・・・・0
6/2=3・・・・0
3/2=1・・・・0
1/2=0・・・・1

下から並べます
10001000
(200=2^7*1+2^6*0+2^5*0+2^4*0+2^3*1+2^2*0+2^1*0+2^0*0だから)

まったく同じです
170
170/2=85・・0
85/2=42・・・1
42/2=21・・・0
21/2=10・・・1
10/2=5・・・0
5/2=2・・・・1
2/2=1・・・・0
1/2=0・・・・1
よって
10101010

同じように繰り返してください

情報処理技術者試験は受けたことないのでわかりませんが
出ないと思うけど
3進数とかに直す場合は2で割っているのを
3で割るのに変えればOK

Q算術シフトしたら、あれ?

16進数ので各4ビット(4桁)で2進数で算術シフトしますが、符号部はぬいて元の16進数に戻すのですか?でもそうすると元の数より大幅に減ってしまいますよね。例題の

例題・A4A6(16)を2ビット算術シフトする。

A4A6(16)=1010 0010 1010 0110 (2)

・左へ2ビットシフトする。

1000 1010 1001 1000(2)=A98(16)

・右へ2ビットシフトする。

1110 1000 1010 1001(2)=8A9(16)

というように、符号部ぬかしたら増えるはずが減ったり、減るはずが増えたりと。なんか変ですよね。

ちなみに符号部すべて入れて考えたら、

左へ算術シフト 8A98(16)
右へ算術シフト E8A9(16)

増えるはずが減って、減るはずが増えるというあべこべになってしまいます。
超基本的ことなんですが、なぜか本に記載されていなかったので書きました。ご協力ください。

Aベストアンサー

まず「A4A6(16)=1010 0010 1010 0110 (2)」の2進数が違います。
正しくは、A) 「1010 0100 1010 0110(2)」です。

で、左へ2ビットシフトすると
B) 「1001 0010 1001 1000(2)」=9298(16)
右へ2ビットシフトすると
C) 「1110 0100 1010 0110(2)」=E4A6(16)

で、簡単に言ってしまえば・・・
符号部が1なので「マイナス値」を表しているので
16進数では、左で少なくなり、右で大きくなっているのでしょう。

負数なので反転させて1加算したものに"-"を付加。
A) 0101 1011 0101 1001+1=0101 1011 0101 1010(16)
B) 0110 1101 0110 0111+1=0110 1101 0110 1000(16)
C) 0001 1011 0101 1001+1=0001 1011 0101 1010(16)

これらを10進数で表すと
5B5A = 10480 + 3072 + 80 + 6 -13638
6D68 = 24576 + 3328 + 96 + 8 -28008
1B5A = 4096 + 2816 + 80 + 10 -7002

こんな感じではないかな。

まず「A4A6(16)=1010 0010 1010 0110 (2)」の2進数が違います。
正しくは、A) 「1010 0100 1010 0110(2)」です。

で、左へ2ビットシフトすると
B) 「1001 0010 1001 1000(2)」=9298(16)
右へ2ビットシフトすると
C) 「1110 0100 1010 0110(2)」=E4A6(16)

で、簡単に言ってしまえば・・・
符号部が1なので「マイナス値」を表しているので
16進数では、左で少なくなり、右で大きくなっているのでしょう。

負数なので反転させて1加算したものに"-"を付加。
A) 0101 1011 0101 1001+1=0101 1011 0101...続きを読む

Q負の二進数

2の補数表現を用いた符号付き8ビットの2進数のとき

10進数で -6

の値はどうなるのでしょう・・・?
16進数時の値と考え方も教えていただければ幸いです・・。



よろしくお願いいたします。

Aベストアンサー

2の補数は、「正」の時のビットを全て反転させてから「1」を加えた値と同じになります。これは、9ビットの「100000000」から6を表す「00000110」を引いたものを表しています。
なので、
00000110
 ↓
11111001
 ↓(+1)
11111010 ←(-6)
になります。
先ほどのように、別のやり方では、
100000000
-00000110
---------
11111010
と同じになります。

また、16進数で表すときは2進数4ビットと1対1に対応しますから
(11111010)2=(FA)16
になります。
0000→0
0001→1
0010→2
0011→3
0100→4
0101→5
0110→6
0111→7
1000→8
1001→9
1010→A
1011→B
1100→C
1101→D
1110→E
1111→F
後は、2進数で求めてから変換するだけです。
いきなり16進数で2の補数を考える人は少ないと思いますよ。

Qエクセル関数:6桁中5桁抽出の方法を教えてください。

6桁の数字の左5桁を抜き出すエクセル関数を教えてください。
「111112」だったら「11111」ってな感じです。
お願いします。

カテゴリ違ったかもしれません、スミマセン(>_<;)

Aベストアンサー

LEFT(セル,5)
です。
なお、右ならRIGHT
ある2桁目から5桁ならMID(セル,2,5)
となります。

Q二進数を負で表す

-256を2進数の9ビットで表すのに困っています

まず256を2進数で表し、(100000000)
それを反転させ1を足す (000000001 + 1)
そうすると答えは000000010になります
しかしこれは最上位のビットが0なので+の値になってしまいます
どうすれば-256を9ビットで表せますでしょうか?

Aベストアンサー

ビットを反転させるのが間違っています。

256 → 10000000
ビットを反転    ↓
      011111111
それに1を足す。 ↓
      10000000

となり、符号付きで考える場合、-256は「10000000」になります。

Qレセプト電算記録について教えてください。

レセプト電算記録について、教えてくださいm(_ _)m

例えば、(33)点滴注射を10日実施したとします。医事会計システムにて、コメント「840000058:xx日」((例)CO,33,1,840000058,日付)コードで実施日をそれぞれ登録後、当月分のレセ電を作成。
医事会計システムにてレセプトプレビューで見てみると、日付の早い順に表示されます。
しかしレセ電を見てみると、日付順には記録されておりませんでした。

レセ電を作成する際、薬剤の異なる点滴注射を10日実施した場合、記録される順番は何を基準に記録されるのでしょうか?

説明不足も多々ある気はしますが、何卒ご教示よろしくお願い致します。

Aベストアンサー

具体的にどこのメーカーが製造した医事会計システムを使用されているでしょうか。

コンピュータシステムってメーカーが違えば当然ですが、操作方法や表示する方式も違ってくると思います。

直接メーカーにお問い合わせした方が解決に早いと思います。

QTCP/IPの二進数と十進数

TCP/IPのIPアドレスとサブネットマスクの計算の所で二進数と十進数が出てきますが、いまいち計算方法がわかりません。
二進数から十進数、十進数から二進数に変換する方法を教えてください。
またそれについて計算方法が記載されているHPでも構いませんので
教えてください。
よろしくお願いいたします。

Aベストアンサー

(途中のスペースとか省略されてちゃんと見えるかどうか不安ですが...)

他の方も書かれていますが、2進数から10進数へは、それぞれの桁の数を
足して行けばいいのです。
たとえば、"1011"を10進数にするには
一番右から2^0(2の0乗),2^1,2^2...とならんでいるので、
2^3*1 + 2^2*0 + 2^1*1 + 2^0*1 =
8*1 + 4*0 + 2*1 + 1*1 =
8 + 0 + 2 + 1 = 11となります。

これは桁が増えても同じで、IPアドレスのような255まで表示する場合
2^7*x + 2^6*x + 2^5*x + 2^4*x + 2^3*x + 2^2*x + 2^1*x + 2^0*x =
となります。
で、もし2進数で"11111111"と書いてあれば(途中省略しますが)
128*1 + 64*1 + 32*1 + 16*1 + 8*1 + 4*1 + 2*1 + 1*1 = 255
となります。

10進数から2進数にする場合は、その逆に
10進数から2^xで割っていった数の余りを書いていくと導きだせます。
例:30の場合

30 を 2で割ると 15 余り 0
15 を 2で割ると 7 余り 1
7 を 2で割ると 3 余り 1
3 を 2で割ると 1 余り 1

これを筆算になおすと(上から下へ割り算をしていく)

2) 30 余り 0
-----
2) 15 余り 1
-----
2) 7 余り 1
-----
2) 3 余り 1
-----
1

となります。
出てきた"余り"を"逆から"ならべると"1110"となって10進数の"30"は
2進数の"1110"と導きだせます。


#ということで、人は片手で31まで数えられるんですね。2進数を使えば。

(途中のスペースとか省略されてちゃんと見えるかどうか不安ですが...)

他の方も書かれていますが、2進数から10進数へは、それぞれの桁の数を
足して行けばいいのです。
たとえば、"1011"を10進数にするには
一番右から2^0(2の0乗),2^1,2^2...とならんでいるので、
2^3*1 + 2^2*0 + 2^1*1 + 2^0*1 =
8*1 + 4*0 + 2*1 + 1*1 =
8 + 0 + 2 + 1 = 11となります。

これは桁が増えても同じで、IPアドレスのような255まで表示する場合
2^7*x + 2^6*x + 2^5*x + 2^4*x + 2^3*x...続きを読む

Q左から右に並んでいるデータを右から左に直せる?

エクセルで横書きで上から下に並んでいる名簿を縦書きで右から左に並ぶように変えたいのです。まずは行と列の入れ替え後、縦書きにしたのですが、それだと左から右に並びます。縦書きだと右から左の方がいいと思うのですが無理でしょうか?

Aベストアンサー

1)1列挿入して、名簿に上から順に通し番号をつける。
2)データの並び替えで通し番号の列を選び、降順にする。
3)行列を入れ替える。

ていうのではだめでしょうか?

Q【php】二進数をフラグとして扱いたい

【php】二進数をフラグとして扱いたい

10011とかの、二進数があった場合

true flase flase true ture みたいな感じで処理できるようにしたいのですが
10011という文字列を それぞれ切っていくという方法しかが浮かんだのですが
なにか、もっといいスマートな方法があれば、アドバイスをお願いいたします。

Aベストアンサー

当たり前すぎて、あまり答えたくはないけど、、、、

元々フラグを利用する理由は、限られた容量の中で、高速に処理させるために考案されたもの、、、あ~もっと歴史は深いか。。。

どちらにしてもフラグを文字列にしてしまっては、何の意味もない。文字列にするくらいなら、配列のほうが使い勝手がいいでしょう。

どうしても文字列がいいってんなら、{} で一文字単位で取り出せるんだから、'10011'{1} == 1 とかでよろい。

# データって元々数値のはずだけど、PHP などの出現で文字列だって考える人が増えとるのかな。文字列なんてデータ表現の一つに過ぎないのに。。。文字化けとかで悩むのもやっぱその辺から来てるのかな。。。

↑はいいとして、フラグはその値を整数値に格納して、ビット演算することで、その効果を発揮しる。

$flag = 0x13;

if ($flag & 0x01) echo '0番目のフラグは on です';
if ($flag & 0x02) echo '1番目のフラグは on です';

if ($flag & 0x03) echo '0,1番目のフラグは on です';
又は、
if ($flag & 0x02 | 0x01) echo '0,1番目のフラグは on です'; // (1)

# (1) http://jp2.php.net/manual/ja/domdocument.load.php など、$option を OR でつなげとはこういうこと。

特定フラグの on/off は XOR
ビット位置指定はシフト。

当たり前すぎて、あまり答えたくはないけど、、、、

元々フラグを利用する理由は、限られた容量の中で、高速に処理させるために考案されたもの、、、あ~もっと歴史は深いか。。。

どちらにしてもフラグを文字列にしてしまっては、何の意味もない。文字列にするくらいなら、配列のほうが使い勝手がいいでしょう。

どうしても文字列がいいってんなら、{} で一文字単位で取り出せるんだから、'10011'{1} == 1 とかでよろい。

# データって元々数値のはずだけど、PHP などの出現で文字列だって考える人が...続きを読む

QUNIXのシェルスクリプトで負数の正負を反転させるには?

UNIXのシェルスクリプトで負の数の符号を反転して生の数にしようと思ったらうまくできませんでした。

#! /bin/sh

NUM=4
NUM2=-$NUM
echo NUM2=$NUM2
とすると
--4
となってしまいました。
また、
NUM2=`expr $NUM * (-1)`
等もやってみたのですが、エラーになりました。
結局、文字列としてawkで'-'を削ったのですが、やり方を間違えてる気がしてなりません。
awkやperl等を使わず、UNIXの単純な機能だけで数の正負を反転させる方法があれば教えてください。

基本情報でよくある2進数の符号の反転のやり方でもできると思うのですが、
10進数だとやり方がよくわかりません、、これでできるなら、このやり方も教えていただけるとありがたいです。

以上、よろしくお願いします。

Aベストアンサー

実行例
a=-3
$ echo `expr \( $a \) \* 2`
-6
$ echo `expr \( $a \) \* \-1`
3

FreeBSDの日本語マニュアルには、
>一般的には、負数となる可能性のある値は括弧で括ります
とあります。

# 他のUNIXのマニュアルにはこのような具体的な記述が無い模様。

また、以下のエスケープが必要です。
"()"は、サブシェルと間違われないように「\(」,「\)」
"*"(乗算)は、ワイルドカード展開されないように 「\*」
"-1"は、オプションに間違わないように「\-1」としています。

2乗して平方根すると必ず正数になるのだが、exprには平方根がなかった。

参考URL:http://www.jp.freebsd.org/cgi/mroff.cgi?subdir=man&lc=1&cmd=&man=expr&dir=jpman-5.4.0%2Fman&sect=0


人気Q&Aランキング