为什么 Java 不支持无符号整数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/430346/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why doesn't Java support unsigned ints?
提问by dsimcha
Why doesn't Java include support for unsigned integers?
为什么 Java 不支持无符号整数?
It seems to me to be an odd omission, given that they allow one to write code that is less likely to produce overflows on unexpectedly large input.
在我看来,这是一个奇怪的遗漏,因为它们允许编写的代码不太可能在意外大输入时产生溢出。
Furthermore, using unsigned integers can be a form of self-documentation, since they indicate that the value which the unsigned int was intended to hold is never supposed to be negative.
此外,使用无符号整数可以是一种自我证明的形式,因为它们表明 unsigned int 打算保存的值永远不应该是负数。
Lastly, in some cases, unsigned integers can be more efficient for certain operations, such as division.
最后,在某些情况下,无符号整数对于某些运算(例如除法)可能更有效。
What's the downside to including these?
包含这些有什么缺点?
采纳答案by Uri
This is from an interview with Gosling and others, about simplicity:
这是来自对Gosling 等人的采访,关于简单性:
Gosling: For me as a language designer, which I don't really count myself as these days, what "simple" really ended up meaning was could I expect J. Random Developer to hold the spec in his head. That definition says that, for instance, Java isn't -- and in fact a lot of these languages end up with a lot of corner cases, things that nobody really understands. Quiz any C developer about unsigned, and pretty soon you discover that almost no C developers actually understand what goes on with unsigned, what unsigned arithmetic is. Things like that made C complex. The language part of Java is, I think, pretty simple. The libraries you have to look up.
Gosling:对于我作为一名语言设计师来说,我现在并不真正将自己视为自己,“简单”的真正含义是我能期望 J. Random Developer 将规范牢记在心。这个定义说,例如,Java 不是——事实上,很多这些语言最终都有很多极端情况,没有人真正理解的东西。询问任何 C 开发人员有关无符号的问题,很快你就会发现几乎没有 C 开发人员真正了解无符号算法的内容,什么是无符号算术。诸如此类的事情使 C 变得复杂。我认为 Java 的语言部分非常简单。您必须查找的库。
回答by akatakritos
http://skeletoncoder.blogspot.com/2006/09/java-tutorials-why-no-unsigned.html
http://skeletoncoder.blogspot.com/2006/09/java-tutorials-why-no-unsigned.html
This guy says because the C standard defines operations involving unsigned and signed ints to be treated as unsigned. This could cause negative signed integers to roll around into a large unsigned int, potentially causing bugs.
这家伙说是因为 C 标准定义了涉及无符号和有符号整数的操作被视为无符号。这可能会导致负有符号整数转为大的无符号整数,从而可能导致错误。
回答by Rob Ottaway
I've heard stories that they were to be included close to the orignal Java release. Oak was the precursor to Java, and in some spec documents there was mention of usigned values. Unfortunately these never made it into the Java language. As far as anyone has been able to figure out they just didn't get implemented, likely due to a time constraint.
我听说过它们将被包含在原始 Java 版本附近。Oak 是 Java 的前身,在一些规范文档中提到了使用的值。不幸的是,这些从未进入 Java 语言。至于任何人都能够弄清楚他们只是没有得到实施,可能是由于时间限制。
回答by Bombe
As soon as signed and unsigned ints are mixed in an expression things start to get messy and you probably willlose information. Restricting Java to signed ints only really clears things up. I'm glad I don't have to worry about the whole signed/unsigned business, though I sometimes do miss the 8th bit in a byte.
一旦有符号和无符号整数混合在表达式中,事情就会开始变得混乱,你可能会丢失信息。将 Java 限制为带符号的整数只会真正解决问题。我很高兴我不必担心整个签名/未签名业务,尽管我有时会错过一个字节中的第 8 位。
回答by Neil Coffey
Reading between the lines, I think the logic was something like this:
从字里行间看,我认为逻辑是这样的:
- generally, the Java designers wanted to simplify the reperttheitroade of data types available
- for everyday purposes, they felt that the most common need was for signed data types
- for implementing certain algorithms, unsigned arithmetic is sometimes needed, but the kind of programmers that would be implementing such algorithms would also have the knowledge to "work round" doing unsigned arithmetic with signed data types
- 通常,Java 设计人员希望简化可用数据类型的全部内容
- 对于日常用途,他们认为最常见的需求是签名数据类型
- 为了实现某些算法,有时需要无符号算术,但是实现此类算法的程序员也将具备使用有符号数据类型进行无符号算术的“工作循环”知识
Mostly, I'd say it was a reasonable decision. Possibly, I would have:
大多数情况下,我会说这是一个合理的决定。可能,我会:
- made byte unsigned, or at least have provided a signed/unsigned alternatives, possibly with different names, for this one data type (making it signed is good for consistency, but when do you ever need a signed byte?)
- done away with 'short' (when did you last use 16-bit signed arithmetic?)
- 使字节无符号,或者至少为这种数据类型提供了一个有符号/无符号替代方案,可能具有不同的名称(使其有符号有利于一致性,但你什么时候需要有符号字节?)
- 取消了“short”(您上次使用 16 位有符号算术是什么时候?)
Still, with a bit of kludging, operations on unsigned values up to 32 bits aren't tooo bad, and most people don't need unsigned 64-bit division or comparison.
尽管如此,通过一些杂凑,对高达 32 位的无符号值进行运算并不算太糟糕,而且大多数人不需要无符号 64 位除法或比较。
回答by starblue
I think Java is fine as it is, adding unsigned would complicate it without much gain. Even with the simplified integer model, most Java programmers don't know how the basic numeric types behave - just read the book Java Puzzlersto see what misconceptions you might hold.
我认为 Java 很好,添加 unsigned 会使它复杂化而没有太多好处。即使使用简化的整数模型,大多数 Java 程序员也不知道基本数字类型的行为 - 只需阅读Java Puzzlers一书,看看您可能持有哪些误解。
As for practical advice:
至于实用建议:
If your values are somewhat arbitrary size and don't fit into
int
, uselong
. If they don't fit intolong
useBigInteger
.Use the smaller types only for arrays when you need to save space.
If you need exactly 64/32/16/8 bits, use
long
/int
/short
/byte
and stop worrying about the sign bit, except for division, comparison, right shift, and casting.
如果您的值有点任意大小并且不适合
int
,请使用long
. 如果它们不适合long
使用BigInteger
。当您需要节省空间时,仅将较小的类型用于数组。
如果您需要的64/32/16/8位,使用
long
/int
/short
/byte
和停止担心符号位,除了分工,比较,右移,和铸造。
See also thisanswer about "porting a random number generator from C to Java".
又见这个回答有关“移植一个随机数发生器从C到Java的”。
回答by mike g
I can think of one unfortunate side-effect. In java embedded databases, the number of ids you can have with a 32bit id field is 2^31, not 2^32 (~2billion, not ~4billion).
我能想到一个不幸的副作用。在 Java 嵌入式数据库中,32 位 id 字段可以拥有的 id 数量是 2^31,而不是 2^32(~20 亿,而不是~40 亿)。
回答by pat
Java does have unsigned types, or at least one: char is an unsigned short. So whatever excuse Gosling throws up it's really just his ignorance why there are no other unsigned types.
Java 确实有无符号类型,或者至少有一个:char 是无符号短整型。所以无论 Gosling 提出什么借口,这实际上只是他的无知为什么没有其他无符号类型。
Also Short types: shorts are used all the time for multimedia. The reason is you can fit 2 samples in a single 32-bit unsigned long and vectorize many operations. Same thing with 8-bit data and unsigned byte. You can fit 4 or 8 samples in a register for vectorizing.
还有 Short 类型:shorts 一直用于多媒体。原因是您可以在单个 32 位 unsigned long 中容纳 2 个样本,并对许多操作进行矢量化。8 位数据和无符号字节也是如此。您可以在一个寄存器中放入 4 或 8 个样本以进行矢量化。
回答by Jyro117
This is an older question and pat did briefly mention char, I just thought I should expand upon this for others who will look at this down the road. Let's take a closer look at the Java primitive types:
这是一个较旧的问题,pat 确实简要地提到了 char,我只是想我应该为其他人扩展这个问题。让我们仔细看看 Java 原始类型:
byte
- 8-bit signed integer
byte
- 8 位有符号整数
short
- 16-bit signed integer
short
- 16 位有符号整数
int
- 32-bit signed integer
int
- 32 位有符号整数
long
- 64-bit signed integer
long
- 64 位有符号整数
char
- 16-bit character (unsigned integer)
char
- 16 位字符(无符号整数)
Although char
does not support unsigned
arithmetic, it essentially can be treated as an unsigned
integer. You would have to explicitly cast arithmetic operations back into char
, but it does provide you with a way to specify unsigned
numbers.
虽然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--;
Yes, there isn't direct support for unsigned integers (obviously, I wouldn't have to cast most of my operations back into char if there was direct support). However, there certainly exists an unsigned primitive data type. I would liked to have seen an unsigned byte as well, but I guess doubling the memory cost and instead use char is a viable option.
是的,没有对无符号整数的直接支持(显然,如果有直接支持,我就不必将大部分操作转换回 char)。但是,肯定存在无符号原始数据类型。我也希望看到一个无符号字节,但我想将内存成本加倍并改为使用 char 是一个可行的选择。
Edit
编辑
With JDK8 there are new APIs for Long
and Integer
which provide helper methods when treating long
and int
values as unsigned values.
JDK8 提供了新的 API Long
,Integer
它们在将long
和int
值视为无符号值时提供辅助方法。
compareUnsigned
divideUnsigned
parseUnsignedInt
parseUnsignedLong
remainderUnsigned
toUnsignedLong
toUnsignedString
compareUnsigned
divideUnsigned
parseUnsignedInt
parseUnsignedLong
remainderUnsigned
toUnsignedLong
toUnsignedString
Additionally, Guavaprovides a number of helper methods to do similar things for at the integer types which helps close the gap left by the lack of native support for unsigned
integers.
此外,Guava提供了许多辅助方法来为整数类型做类似的事情,这有助于缩小由于缺乏对unsigned
整数的本机支持而留下的差距。
回答by Denis Co
The reason IMHO is because they are/were too lazy to implement/correct that mistake. Suggesting that C/C++ programmers does not understand unsigned, structure, union, bit flag... Is just preposterous.
恕我直言,原因是因为他们/太懒于实施/纠正该错误。暗示 C/C++ 程序员不懂无符号、结构、联合、位标志......简直是荒谬。
Ether you were talking with a basic/bash/java programmer on the verge of beginning programming a la C, without any real knowledge this language or you are just talking out of your own mind. ;)
在开始用 C 语言编程时,您正在与基本/bash/java 程序员交谈,而您对这种语言没有任何真正的了解,或者您只是在胡言乱语。;)
when you deal every day on format either from file or hardware you begin to question, what in the hell they were thinking.
当您每天处理来自文件或硬件的格式时,您开始质疑,他们到底在想什么。
A good example here would be trying to use an unsigned byte as a self rotating loop. For those of you who do not understand the last sentence, how on earth you call yourself a programmer.
这里的一个很好的例子是尝试使用无符号字节作为自旋转循环。对于那些不理解最后一句话的人,你到底是如何称自己为程序员的。
DC
直流电