皆さんいつもお世話になっております。
SweetSugarと申します。
本日は「符号あり」「符号なし」の意味についてお聞きしたいことがあります。
また、本文はJavaであることを前提として書いてあります。説明の不十分な点がございましたら申し訳ございません。
まず初めに、例えばbyte型の場合は表現できる値の範囲として**「-128〜127」であるかと思います。
私はこれを「符号あり」と理解しています。
よって「符号なし」とは「符号あり」のマイナスの範囲を無くし正の範囲をその分増やした「0〜255」**であると理解しています。
この考え方は正しいのでしょうか。仮に正しいとした場合、符号ありなしの必要性についても伺いたく思います。
次に実際のコードを作成する場合、例えば**「 ストリームから次の2byte分のバイナリデータを”符号なしの16bit長の2進数”として取得しなさい 」と指示があった場合にそれは「 DataInputStream#readUnsignedShort() 」**を使用して取得したint型の返り値が目的のものという事になるのでしょうか。
現在、符号なしやありの意味そしてバイナリデータ取得の方法などについてイメージをはっきりとつかめておりません。
お忙しいと事申し訳ございませんがご教授いただけると幸いです。
よろしくお願いいたします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
解釈の通りで正しいです。
二進値では数字を0と1のみで表現するので負数をどうするかといった課題があります。たとえば―1は8ビットの符号付二進数で11111111と表現されます。もちろん、これは符号無二進数としても意味のあるものであり、この場合は255という数字になります。
つまり、同一のビット列であっても符号付で解釈するか符号無で解釈するかによって異なる値となります。ですので二進値の変換の際にはどちらの方法を使うかを決めておく必要があります。
ちなみに、負数の表現には「二の補数」というルールを用いることが一般的です。このルールでは、最上位ビットが1である場合を負数と定め、この絶対値は「当該ビット列のビット反転に1を加えた値」となります。例えば「11111111」の絶対値は、ビット反転して「00000000」に1を加えて「1」となります。
このルールですと、負数と非負数の加減算を自然に定義できます。また、ビット拡張もしやすいです。非負数の場合は上位ビットを0で埋めるだけで拡張でき、負数の場合は上位ビットを1で埋めるだけで拡張できます。(言い換えれば最上位ビットをそのまま上の桁に追加するだけで良い)
投稿2018/02/07 11:48
総合スコア4830
0
- 符号無しと符号有りの考え方について
それで正しいです。
必要性という点で言えば、符号あり、そして2の補数について学んでいただくのがいいかと思います。
上手い具合に符号ありに拡張できているのです。
- ストリームからの読み込み
ストリーム上のデータは、本質的にはバイトデータの羅列です。ですから、「ここからの2バイトは整数として読む」「ここからの10バイトは文字列として読む」といったように、どう解釈するかはプログラム側で指定してやらねばなりません。データに型の属性が含まれているわけではないからです。
※プロトコルという形で、「この位置のデータが1なら、その後の2バイトを読んで……」という手順を決めることはできますが、その場合でもバイト列を解釈しながら読んでいるのは変わりありません
なお、2バイト以上のデータを数値として読む場合、注意が必要になります。実行している環境、そしてデータを作った環境によって、複数バイトからなる整数の場合、どちらが上位バイトになるかが異なってくるからです。
データとして 0x0123(10進数で291)というデータだとして、
- インテル系列の場合 23 01
- モトローラ系列の場合 01 23
と、順番が逆転します。(インテル系の並び方を「リトルエンディアン」、モトローラ系を「ビッグエンディアン」と呼びます)
※CPU によってはどっちで動くか変えられるようなものもある
投稿2018/02/06 14:30
総合スコア13703
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/02/10 04:38
2018/02/11 10:10
0
ベストアンサー
考え方は合っていますよ。
(2進数)「1111 1111」= (16進数)0xFF = (符号無し10進数)255 or (符号有り10進数)-128
2進数は1繰り上がる毎に2^n乗になるので、符号無し10進数にすると、
「1111 1111」は「(128+64+32+16) + (8+4+2+1)」= 255。
この先頭bitをプラス128かマイナス128か、符号として利用しているのが符号有りです。
上の式の128がマイナス128になるので、-128~127を表現することになります。
符号の有無の必要性については、そのまま計算結果でマイナスになる数字の必要性があるかってことになります。
全ての計算結果がプラスで表せる訳ではありません。
例えば符号無しで「1-2」を計算すると-1は表現出来ません。範囲外の数字なので255とするか、エラーになります。
だからといって全ての型を符号有りの大きい型にすると、無駄に重たいデータになります。
使う値を必要に応じて最低限使うことが大事です。
2Byte取得は、bit演算の計算式にするとイメージしやすいです。
「readUnsignedShort」は、 ((byte[1] & 0xff) << 8) + (byte[0] & 0xff)
と同じです。
詳しくは「bit演算」で検索すると良いです。
JavaはByte型が符号有りしか無い上、
bit演算の右シフトが符号有りシフト「>>」と符号無しシフト「>>>」と2種類あるので、
使う時に混乱するかもしれませんが、
2進数の原理を理解せずにバイナリデータを扱うと、
予想外の計算結果になっても原因がわからないままになってしまいます。
投稿2018/02/06 14:48
総合スコア442
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/02/07 15:28
2018/02/07 16:16
2018/02/08 15:40
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/02/07 15:34