394

Javaに符号なし整数のサポートが含まれていないのはなぜですか?

予想外に大きな入力でオーバーフローが発生する可能性が低いコードを記述できることを考えると、奇妙な省略のように思われます。

さらに、unsigned inintを使用することは、unsigned intが保持することを意図した値が負になることは決してないことを示しているため、自己文書化の形式になる可能性があります。

最後に、場合によっては、除算などの特定の操作では、符号なし整数の方が効率的です。

これらを含めることの欠点は何ですか?

4

16 に答える 16

206

これは、単純性についてのGoslingや他の人へのインタビューからのものです。

Gosling:言語デザイナーとしての私にとって、最近はあまり自分自身を数えていませんが、「単純な」というのは、J。RandomDeveloperが仕様を頭に入れてくれることを期待できるということでした。その定義は、たとえば、Javaはそうではないことを示しています。実際、これらの言語の多くは、多くのコーナーケースになり、誰も実際には理解できません。符号なしについてC開発者にクイズを出してみると、すぐに、符号なしで何が起こっているのか、符号なし演算とは何かを実際に理解しているC開発者はほとんどいないことがわかります。そのようなことでCは複雑になりました。Javaの言語部分は、かなり単純だと思います。あなたが調べなければならない図書館。

于 2009-01-10T01:43:35.853 に答える
55

行間を読むと、ロジックは次のようなものだったと思います。

  • 一般に、Java 設計者は、利用可能なデータ型のレパートリーを単純化したいと考えていました。
  • 日常的な目的のために、最も一般的な必要性は署名されたデータ型であると彼らは感じました
  • 特定のアルゴリズムを実装するために、符号なし算術演算が必要になることがありますが、そのようなアルゴリズムを実装するようなプログラマーは、符号付きデータ型で符号なし算術演算を「回避」する知識も持っています。

ほとんどの場合、それは合理的な決定だったと思います。おそらく、私は持っているでしょう:

  • バイトを符号なしにするか、少なくともこの 1 つのデータ型に対して、おそらく異なる名前で、符号付き/符号なしの代替を提供しました (符号付きにすることは一貫性のために良いですが、符号付きバイトが必要になるのはいつですか?)
  • 'short' を廃止しました (最後に 16 ビットの符号付き演算を使用したのはいつですか?)

それでも、多少の手間はかかりますが、32 ビットまでの符号なし値の操作はそれほど悪くなく、ほとんどの人は符号なし 64 ビットの除算や比較を必要としません。

于 2009-01-10T04:29:03.693 に答える
22

これは古い質問であり、pat は char について簡単に言及しましたが、今後これを検討する他の人のためにこれを拡張する必要があると思いました。Java プリミティブ型を詳しく見てみましょう。

byte- 8 ビット符号付き整数

short- 16 ビット符号付き整数

int- 32 ビット符号付き整数

long- 64 ビット符号付き整数

char- 16 ビット文字 (符号なし整数)

は算術をサポートしていcharませんが、基本的に整数unsignedとして扱うことができます。unsigned算術演算を に明示的にキャストする必要がありますが、数値charを指定する方法が提供されますunsigned

char a = 0;
char b = 6;
a += 1;
a = (char) (a * b);
a = (char) (a + b);
a = (char) (a - 16);
b = (char) (b % 3);
b = (char) (b / a);
//a = -1; // Generates complier error, must be cast to char
System.out.println(a); // Prints ? 
System.out.println((int) a); // Prints 65532
System.out.println((short) a); // Prints -4
short c = -4;
System.out.println((int) c); // Prints -4, notice the difference with char
a *= 2;
a -= 6;
a /= 3;
a %= 7;
a++;
a--;

はい、符号なし整数の直接サポートはありません (明らかに、直接サポートがあれば、ほとんどの操作を char にキャストする必要はありません)。ただし、符号なしのプリミティブ データ型は確かに存在します。符号なしバイトも見たかったのですが、メモリ コストを 2 倍にして、代わりに char を使用することが実行可能なオプションであると思います。


編集

JDK8 には、 and の値を符号なし値として扱うときにヘルパー メソッドを提供するLongand用の新しい API があります。Integerlongint

  • compareUnsigned
  • divideUnsigned
  • parseUnsignedInt
  • parseUnsignedLong
  • remainderUnsigned
  • toUnsignedLong
  • toUnsignedString

さらに、Guavaは、整数型に対して同様のことを行うためのヘルパー メソッドを多数提供します。これは、整数のネイティブ サポートの欠如によって残されたギャップを埋めるのに役立ちunsignedます。

于 2011-07-27T20:22:49.883 に答える
17

Java には unsigned 型、または少なくとも 1 つの型があります。char は unsigned short です。したがって、Gosling がどのような言い訳を投げかけたとしても、それは本当に彼の無知にすぎません。

また、ショート タイプ: ショートはマルチメディアで常に使用されます。その理由は、2 つのサンプルを 1 つの 32 ビット符号なし long に収め、多くの操作をベクトル化できるからです。8 ビット データと符号なしバイトでも同じです。ベクトル化のためにレジスターに 4 つまたは 8 つのサンプルを収めることができます。

于 2009-10-12T07:20:10.270 に答える
15

符号付き整数と符号なし整数が式に混在するとすぐに、物事が混乱し始め、おそらく情報失われます。Java を signed int に制限しても、問題が解決するだけです。署名付き/署名なしビジネス全体について心配する必要がないことを嬉しく思いますが、バイトの 8 番目のビットを見逃すことがあります。

于 2009-01-10T02:05:31.143 に答える
13

http://skeletoncoder.blogspot.com/2006/09/java-tutorials-why-no-unsigned.html

この男は、C標準では、unsignedおよびsignedintを含む操作がunsignedとして扱われるように定義されているためだと言います。これにより、負の符号付き整数が大きなunsigned intにロールアラウンドし、バグが発生する可能性があります。

于 2009-01-10T01:42:05.060 に答える
12

Javaはそのままで問題ないと思いますが、unsignedを追加すると複雑になり、あまりメリットがありません。単純化された整数モデルを使用しても、ほとんどの Java プログラマーは基本的な数値型がどのように動作するかを知りません。本Java Puzzlersを読んで、どのような誤解を抱いているかを確認してください。

実践的なアドバイスについては、次のとおりです。

  • 値がやや恣意的なサイズで、 に収まらない場合はint、 を使用してlongください。long使用に適さない場合BigInteger

  • スペースを節約する必要がある場合は、配列に対してのみ小さい型を使用してください。

  • 正確に 64/32/16/8 ビットが必要な場合は、long/ int/ short/byteを使用し、除算、比較、右シフト、およびキャストを除いて、符号ビットについて心配する必要はありません。

「C から Java への乱数ジェネレーターの移植」に関するこの回答も参照してください。

于 2009-01-10T08:39:20.100 に答える
8

この投稿が古すぎることは承知しています。ただし、Java 8 以降では、データ型を使用して、最小値が 0 で最大値が 2 32 -1intの符号なし 32 ビット整数を表すことができます。クラスを使用して、データ型を符号なし整数として使用し、などの静的メソッドをクラスに追加して、符号なし整数の算術演算をサポートします。IntegerintcompareUnsigned()divideUnsigned()Integer

于 2014-01-30T09:18:46.580 に答える
6

JDK8では、それらをある程度サポートしています。

Gosling の懸念にもかかわらず、Java で unsigned 型が完全にサポートされる可能性はまだあります。

于 2013-02-24T15:30:09.313 に答える
5

オリジナルのJavaリリースの近くに含まれる予定だったという話を聞いたことがあります。オークはJavaの前身であり、一部の仕様書には、使用された値についての言及がありました。残念ながら、これらはJava言語にはなりませんでした。おそらく時間の制約のために、誰もが実装されなかったことを理解できた限りです。

于 2009-01-10T01:45:42.433 に答える
5

私はかつて、C++ 標準委員会の誰かと一緒に C++ のコースを受講したことがあります。その人は、(1) 符号なし整数を使用するほとんどのプログラムは、符号付き整数でも同じように機能し、これは、 (2) 符号なし整数を使用すると、整数演算オーバーフローや、符号付き型と符号なし型の間の変換時に重要なビットが失われるなど、作成は簡単ですが、デバッグが困難な問題が多数発生します。符号付き整数を使用して誤って 0 から 1 を減算すると、プログラムが 2^32 - 1 にラップアラウンドする場合よりも多くの場合、より迅速にプログラムがクラッシュし、バグを見つけやすくなります。符号なし算術演算を使用することを選択したので、何をしているのかを知っていると仮定します。また、

昔、メモリが限られており、プロセッサが一度に 64 ビットで自動的に動作しなかったときは、すべてのビットがより多くカウントされていたため、符号付きバイトと符号なしバイトまたは short を比較することが実際にはより頻繁に重要になり、明らかに正しい設計上の決定でした。現在、ほとんどすべての通常のプログラミングでは、signed int を使用するだけで十分です。プログラムで 2^31 - 1 より大きい値を使用する必要がある場合は、多くの場合とにかく long が必要です。long を使用する領域に入ると、2^63 - 1 の正の整数を実際に使用できない理由を考え出すのはさらに難しくなります。128 ビット プロセッサに移行するたびに、問題はさらに少なくなります。

于 2016-11-01T19:13:40.967 に答える
1

unsignedタイプは純粋な悪だからです。

unsigned - intin Cが生成するという事実unsignedは、さらに悪いことです。

これは、私を何度も悩ませた問題のスナップショットです。

// We have odd positive number of rays, 
// consecutive ones at angle delta from each other.
assert( rays.size() > 0 && rays.size() % 2 == 1 );

// Get a set of ray at delta angle between them.
for( size_t n = 0; n < rays.size(); ++n )
{
    // Compute the angle between nth ray and the middle one.
    // The index of the middle one is (rays.size() - 1) / 2,
    // the rays are evenly spaced at angle delta, therefore
    // the magnitude of the angle between nth ray and the 
    // middle one is: 
    double angle = delta * fabs( n - (rays.size() - 1) / 2 ); 

    // Do something else ...
}

もうバグに気づきましたか?私は、デバッガーに介入した後にのみ見たことを告白します。

nは unsigned 型であるためsize_t、式全体がn - (rays.size() - 1) / 2として評価されunsignedます。その式は、中央の光線から 3 番目の光線の符号付きの位置になるように意図されていますn。左側の中央の光線から 1 番目の光線は位置 -1 になり、右側の最初の光線は位置 +1 になります。絶対値を取り、角度を掛けると、光線と中央の光線deltaの間の角度が得られます。n

残念ながら、上記の式には符号なしの悪が含まれており、たとえば -1 に評価される代わりに、2^32-1 に評価されました。その後の への変換によりdouble、バグが封印されました。

算術演算の誤用によって引き起こされたバグが 1 つまたは 2 つ発生した後、unsigned取得した余分なビットが余分な問題に見合う価値があるかどうか疑問に思うようになります。unsignedバイナリマスクなどの非算術演算には引き続き使用しますが、可能な限り算術での型の使用を回避しようとしています。

于 2016-02-02T22:36:56.023 に答える
-2

不幸な副作用を 1 つ思いつくことができます。Java 組み込みデータベースでは、32 ビット ID フィールドで使用できる ID の数は 2^32 ではなく 2^31 です (~40 億ではなく~20 億)。

于 2009-01-11T23:56:55.957 に答える
-8

私見の理由は、彼らがその間違いを実装/修正するのが面倒だからです。C/C++ プログラマーが符号なし、構造体、共用体、ビット フラグを理解していないことを示唆することは、ばかげています。

C言語のプログラミングを始めようとしているbasic / bash / Javaプログラマーと、この言語についての本当の知識がなくても話しているか、自分の頭から離れて話しているだけです。;)

ファイルまたはハードウェアのフォーマットを毎日扱っていると、一体何を考えているのか疑問に思うようになります。

ここでの良い例は、自己回転ループとして符号なしバイトを使用しようとすることです。最後の文を理解していない人のために、一体どうして自分をプログラマーと呼んでいるのでしょう。

DC

于 2012-03-10T21:37:56.123 に答える