符号付き整数と符号なし整数


395

符号付き整数と符号なし整数の違いは次のとおりです。

  1. 符号なしは、より大きな正の値を保持でき、負の値は保持できません。
  2. 符号なしでは、先頭ビットを値の一部として使用しますが、符号付きバージョンでは、左端のビットを使用して、数値が正か負かを識別します。
  3. 符号付き整数は、正数と負数の両方を保持できます。

他に違いはありますか?


6
0は正でも負もないので、符号なし整数には正の値の代わりに非負の値という用語を使用する方が適切です。
ダニエル

回答:


344

符号なしは、より大きな正の値を保持でき、負の値は保持できません。

はい。

符号なしでは、先頭ビットを値の一部として使用しますが、符号付きバージョンでは、左端のビットを使用して、数値が正か負かを識別します。

符号付き整数を表す方法はいくつかあります。視覚化する最も簡単な方法は、左端のビットをフラグ(符号と大きさ)として使用することですが、より一般的なのは2の補数です。どちらも最近のほとんどのマイクロプロセッサで使用されています。浮動小数点は符号と大きさを使用し、整数演算は2の補数を使用します。

符号付き整数は、正数と負数の両方を保持できます。

はい


これがまさにそのテキストかどうかはわかりませんが、別のリンクを見つけました。PDFの9ページ(実際には本の38ページです)に移動すると、データ表現(セクション1.3)というセクションが表示されます。上記のすべての説明があります。lms.uop.edu.jo/lms/pluginfile.php/2420/mod_resource/content/1/...
WeirdElfB0y

92

x86のハードウェアレベルの違いについて説明します。コンパイラーを作成している場合やアセンブリー言語を使用している場合を除き、これはほとんど関係ありません。しかし、知っておくと便利です。

まず、x86は、符号付き数値の2の補数表現をネイティブでサポートしています。他の表現を使用することもできますが、これにはより多くの命令が必要になり、一般にプロセッサ時間の無駄になります。

「ネイティブサポート」とはどういう意味ですか?基本的には、符号なしの数値に使用する一連の命令と、符号付きの数値に使用する一連の命令があることを意味します。符号なしの数値は、符号付きの数値と同じレジスタに格納でき、実際にプロセッサを気にすることなく、符号付きと符号なしの命令を混在させることができます。数値が署名されているかどうかを追跡し、適切な指示を使用するのはコンパイラ(またはアセンブリプログラマ)の責任です。

まず、2の補数には、加算と減算が符号なしの数値とまったく同じであるという特性があります。数値が正でも負でも違いはありません。(あなただけ先に行くと、そうADDSUB心配することなく、あなたの数字。)

比較に関しては、違いが明らかになり始めています。x86にはそれらを区別する簡単な方法があります。上/下は符号なしの比較を示し、大きい/小さいは符号付きの比較を示します。(たとえばJAE、「以上の場合はジャンプ」を意味し、符号なしです。)

また、符号付き整数と符号なし整数を処理するための乗算と除算の2つのセットがあります。

最後に、オーバーフローなどをチェックする場合は、符号付きの数値と符号なしの数値で異なる方法でチェックします。


符号なし数値と符号付き数値とはどういう意味ですか、私が尋ねたいのは、符号なし整数a = 2と符号付き整数b = 2を書いて、両方とも符号付きまたは符号なしであるかどうかです。に割り当てるか、負の符号があるかどうかに依存しますか?これはしばらくの間私を悩ませてきました。
Suraj Jain

@SurajJainの符号付きおよび符号なしは型を参照します。変数または式が負の値を持つことが可能かどうかを示します。
Artelius 16

私は次の疑問を持っています、私は質問をしました、まだ満足のいく答えはありません。ここでそれを見てください、stackoverflow.com
Suraj Jain

62

彼は署名付きと署名なしについてのみ尋ねた。なぜ人々はこれに余分なものを追加しているのか分からない。その答えをお話ししましょう。

  1. 符号なし:0から255までの負でない値のみで構成されます。

  2. 署名済み:負の値と正の値の両方で構成されていますが、次のような異なる形式です

    • 0から+127
    • -1から-128

そして、この説明は8ビットの数体系についてです。


17

完全性のためのほんのいくつかのポイント:

  • この答えは整数表現のみを説明しています。浮動小数点には他の答えがあるかもしれません。

  • 負の数の表現は異なる場合があります。今日使用される最も一般的な(はるかに-今日ではほぼ普遍的です)は、2の補数です。他の表現には、1の補数(かなりまれ)と符号付きの大きさ(ほとんどありませんが、おそらく博物館の作品でのみ使用されます)が含まれます。

  • 2の補数を使用する場合、変数は正数よりも負数の範囲を(1だけ)大きく表現できます。これは、正の数にはゼロが含まれているため(符号ビットがゼロに設定されていないため)、負の数は含まれていないためです。つまり、最小の負の数の絶対値を表すことができません。

  • 1の補数または符号付きの大きさを使用する場合、正または負の数としてゼロを表すことができます(これは、これらの表現が通常使用されない2つの理由の1つです)。


unsigned int a = -2、signed int b = -2と書いた場合、基になる表現は同じになりますが、負の値が指定された符号なし数値を使用するのは良くないことですが、それを指定した場合、何になりますか基になる表現?
Suraj Jain

1
マイナーニグル:符号と大きさはIEEE浮動小数点で使用されるため、実際には非常に一般的です。:-)
alastair 2017

14

クラスで学んだことによると、符号付き整数は正数負数の両方を表すことができますが、符号なし整数は負でないだけです。

たとえば、8ビットの数値を見てみましょう。

符号なしの0255

符号付き値の範囲は-128〜です127


11

ポイント2を除くすべてが正しいです。符号付き整数にはさまざまな表記法があり、最初の実装を使用する実装もあれば、最後の実装を使用する実装もあれば、まったく異なるものを使用する実装もあります。それはすべて、使用しているプラ​​ットフォームによって異なります。


それはリトルエンディアンとビッグエンディアンのことですか。
vIceBerg 2008年

リトルエンディアンとビッグエンディアンの違いは、プラットフォーム上のバイトの順序に関係しています。リトルエンディアンは0xFF 0xFE 0x7Fを実行し、ビッグエンディアンは0x7F 0xFE 0xFFを実行します。
Jasper Bekkers、2008年

10

もう1つの違いは、サイズの異なる整数間で変換する場合です。

たとえば、バイトストリームから整数を抽出する場合(簡単にするために16ビットと言います)、符号なしの値を使用する場合は、次のようにします。

i = ((int) b[j]) << 8 | b[j+1]

(おそらく2 番目のバイトをキャストする必要がありますが、コンパイラーは正しいことをすると思います)

符号付きの値では、符号拡張について心配する必要があります。

i = (((int) b[i]) & 0xFF) << 8 | ((int) b[i+1]) & 0xFF

5

一般的に言ってそれは正しいです。なぜあなたが違いを探しているのかについての詳細を何も知らなければ、私は署名されたものと署名されていないものの間の他の差別化要因を考えることができません。


4

他の人が言ったことに加えて、Cでは、符号なし整数をオーバーフローさせることはできません。動作は、モジュラス算術であると定義されています。符号付き整数をオーバーフローさせることができます。理論的には(現在の主流システムでは実際には行われていませんが)、オーバーフローによって障害が発生する可能性があります(おそらくゼロ除算障害に似ています)。


1
符号付き整数オーバーフローは未定義の動作を引き起こすことに注意してください。最近のコンパイラーはこれを発見し、それを悪用してプログラムを予期しないが技術的に正当な方法で変更することについて非常に積極的です。これは、7年前よりもはるかに大きな問題です。
Jonathan Leffler、2015年

4
  1. はい、符号なし整数は大きな値を格納できます。
  2. いいえ、正の値と負の値を表示する方法はいくつかあります。
  3. はい、符号付き整数には正と負の両方の値を含めることができます。

4

(2番目の質問への回答)符号ビットのみを使用して(2の補数ではなく)、最終的に-0にすることができます。あまりきれいではありません。


ただ、基本的には、それは両方のこれらの数字は、ベース2ある10 == 00ということ、この答えに追加する

4

Cの符号付き整数は数値を表します。aおよびbが符号付き整数型の変数である場合、標準では、コンパイラが式をそれぞれの値の算術合計以外のものにa+=b格納することを要求しませんa。確かに、算術合計がに収まらない場合、aプロセッサそこに置くことができない可能性がありますが、標準では、コンパイラが値を切り捨てたりラップしたりする必要はありません。それらのタイプの制限。標準では必要ありませんが、Cの実装では、算術オーバーフローを符号付きの値でトラップできます。

Cの符号なし整数は、2のべき乗を法として合同である整数の抽象代数環として動作します。ただし、より大きな型への変換や操作を伴うシナリオを除きます。任意のサイズの整数を32ビット符号なし型に変換すると、その整数mod 4,294,967,296に一致するものに対応するメンバーが生成されます。2から3を引くと、4,294,967,295になります。これは、3に一致するものを4,294,967,295に一致するものに追加すると、2に一致するものになるためです。

抽象代数リング型は、多くの場合便利です。残念ながら、Cは型がリングとして動作するかどうかの決定要因として符号付きを使用します。さらに悪いことに、符号なしの値は、より大きな型に変換されるとリングメンバーではなく数値として扱われ、数値よりも小さい符号なしの値intは、算術が実行されると数値に変換されます。場合vuint32_t等しい4,294,967,294、その後v*=v;にする必要がありますv=4。残念ながら、intが64ビットの場合、何v*=v;ができるかわかりません。

標準のままで、代数環に関連する動作が必要な場合は符号なしの型を使用し、数値を表現する場合は符号付きの型を使用することをお勧めします。Cが区別をその方法で描いたのは残念ですが、それは彼らがそうであるものです。


3

符号なし整数は、符号付き整数よりも特定の罠に捕まる可能性がはるかに高いです。トラップは、上記の1と3は正しいが、どちらのタイプの整数にも、「保持」できる範囲外の値を割り当てることができ、暗黙のうちに変換されるという事実から来ています。

unsigned int ui = -1;
signed int si = -1;

if (ui < 0) {
    printf("unsigned < 0\n");
}
if (si < 0) {
    printf("signed < 0\n");
}
if (ui == si) {
    printf("%d == %d\n", ui, si);
    printf("%ud == %ud\n", ui, si);
}

これを実行すると、両方の値が-1に割り当てられ、宣言が異なっていても、次の出力が得られます。

signed < 0
-1 == -1
4294967295d == 4294967295d

0

Cの符号付き値と符号なし値の唯一の保証された違いは、符号付き値が負、0、または正であり、符号なし値が0または正である場合があることです。問題は、Cが型の形式を定義しないことです(そのため、整数が2の補数であること知りません)。厳密に言えば、あなたが言及した最初の2つの点は正しくありません。


0

組み込みシステムでプログラミングする場合は、符号なし整数を使用する必要があります。ループでは、符号付き整数が必要ない場合、符号なし整数を使用すると、そのようなシステムを設計するために必要な安全性を節約できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.