关于语言设计:为什么Java不支持无符号整数?

Why doesn't Java support unsigned ints?

为什么Java不支持无符号整数呢?

在我看来,这是一个奇怪的遗漏,因为它们允许我们编写代码,这样就不太可能在异常大的输入上产生溢出。

此外,使用无符号整数可以是一种自记录的形式,因为它们表示无符号int要保存的值永远不应该是负数。

最后,在某些情况下,无符号整数对于某些操作(如除法)更有效。

把这些放进去有什么坏处?


这是从一个采访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.


阅读之间的线,我认为是这样的:有逻辑

  • 通常,Java的设计者想要的曲目可以简化数据类型
  • 为日常用途,他们觉得最需要什么数据类型的通用符号
  • 为实现某些算法的无符号算术,有时需要的是小,但程序员是搜索算法的实施是一个"知识工作轮做"无符号算术与符号数据类型

不,我说这是一个合理的决策。可能,我会:

  • 制造的无符号字节,或至少有符号/无符号提供一个替代,这可能与不同的名称,这一数据类型(它是制作有好的一致性,但当你需要的有符号字节(?)
  • 完成了与"短"(你什么时候负载使用的16位有符号的算术?)

安静,有位无符号值kludging,业务上向32位不啊浴,和最不需要的人或部门无符号64位比较。


这是一个古老的问题,帕特确实简短地提到了查尔,我只是想我应该把这个问题扩展到其他人,他们会在这条路上看到这个问题。让我们仔细看看Java原语类型:

byte—8位有符号整数

short16位有符号整数

int—32位有符号整数

long64位有符号整数

char16位字符(无符号整数)

虽然char不支持unsigned算法,但它本质上可以看作一个unsigned整数。您必须显式地将算术运算转换回char中,但它提供了一种指定unsigned数字的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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)。但是,确实存在一个无符号基元数据类型。我也希望看到一个无符号字节,但我想加倍的内存成本,而使用char是一个可行的选择。

编辑

有了JDK8,longInteger有了新的API,它们在将longint值视为无符号值时提供了辅助方法。

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

此外,guava还提供了许多辅助方法来为at整数类型执行类似的操作,这有助于缩小由于缺少对unsigned整数的本机支持而留下的空白。


Java也有无符号类型,或至少一个无符号的字符:短。任何借口,那么它将雏鹅动真的只是他的ignorance为什么没有其他的无符号类型。

所以短短裤类型:多媒体是使用所有的时间。原因是你可以安装2在A单样本的32位无符号整型和vectorize许多操作。同样的事情与8位无符号字节的数据。你可以安装4或8个样本vectorizing A寄存器。


有符号和无符号整型。特别是在表达的东西是混合在开始和你可能想得到松散混乱的信息。一个有符号整型restricting Java只有真正将事情放大。我很高兴我不担心有符号/无符号的整体业务,虽然我有时做小姐的8位字节中。


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

这家伙说因为C标准定义无符号和有符号整型操作涉及处理为无符号的。这是因为有符号整数负推出在一个大的无符号整型,造成潜在的错误。


我认为它是一个精细的Java,它是没有多complicate添加符号增益。即使在最简化的整数模型,Java程序员不知道基本数值类型的行为只是读的书misconceptions Java puzzlers看看你会微笑。

AS的实用建议:

  • 如果你的价值观是在任意大小和不intlong成配合使用。如果他们don’t longBigInteger成配合使用。

  • 使用更小的数组类型只有当你需要节省空间。

  • 如果你需要完全的64/32/16/8位,使用long/ / / byteintshort停止位和担心的一点,除了正确的划分,比较,移位,和铸造。

所以这个答案是"湖从随机数发生器C移植到Java。


我知道这个帖子太老了,但是,对于您的兴趣,在Java 8和以后,您可以使用EDCOX1×2的数据类型来表示一个无符号的32位整数,它的最小值为0,最大值为232。1。使用Integer类将int数据类型用作无符号整数,并将compareUnsigned()divideUnsigned()等静态方法添加到Integer类中,以支持无符号整数的算术运算。


有了JDK8,它确实对它们有一些支持。

尽管GOOLLN的担忧,我们仍然可以看到Java中的无符号类型的完全支持。


我听到的故事,他们都太靠近原包含的Java版本。橡树是一个Java的前体,和在一些大学usigned规格文件有提到的价值。本论文不让它到Java语言。只要能找到任何人。他们只是不可能得到实现,由于时间约束。


我曾经在C++标准委员会上与C++进行了一个课程,它暗示Java做出正确的决定避免使用无符号整数,因为(1)大多数使用无符号整数的程序可以和有符号整数一样好,这在人们如何思考方面更自然,并且(2)使用无符号整数会导致大量EAS。在有符号类型和无符号类型之间转换时,创建但很难调试整数算术溢出和丢失有效位等问题。如果使用有符号整数错误地从0中减去1,它通常会更快地导致程序崩溃,并使查找bug比将其包装到2^32-1更容易,并且编译器、静态分析工具和运行时检查必须假定您知道自己在做什么,因为您选择使用无符号算术。此外,负数(如-1)通常可以表示一些有用的内容,例如字段被忽略/默认/未设置,而如果使用无符号,则必须保留一个特殊值(如2^32-1或类似值)。

很久以前,当内存有限,处理器不能同时在64位上自动运行时,每一位的计数都要多得多,因此,有符号字节和无符号字节或短路实际上更重要,显然是正确的设计决策。现在,在几乎所有常规的编程情况下,只使用带符号的int就足够了,如果程序确实需要使用大于2^31-1的值,那么通常只需要一个long。一旦你进入了使用long的领域,就更难找到一个原因来解释为什么你真的不能通过2^63-1正整数。每当我们使用128位处理器时,问题就更少了。


你的问题是"为什么Java不支持无符号的int"?好的。

我对你的问题的回答是Java想要所有的原始类型:字节、char、短、int和长应该分别被当作字节、字、dword和qword来对待,就像汇编一样,Java操作符除了它的字符之外,所有的原始类型都有签名操作,但是只有char,它们只有16位的无符号。好的。

所以静态方法假设也是32位和64位的无符号操作。好的。

您需要最后一个类,它的静态方法可以为无符号操作调用。好的。

您可以创建这个最后一个类,调用它您想要的任何名称,并实现它的静态方法。好的。

如果您不知道如何实现静态方法,那么这个链接可能会对您有所帮助。好的。

在我看来,Java根本不类似于C++,如果它既不支持无符号类型,也不支持运算符重载,那么我认为Java应该被视为完全不同于C++和C.的语言。好的。

顺便说一下,它在语言名称上也完全不同。好的。

所以我不建议在Java中键入类似于C的代码,我不建议在任何情况下键入与C++类似的代码,因为在Java中,您将无法在C++中完成下一步要做的事情,即代码不会继续像C++一样,对我来说,这样的代码是不好的,要改变中间的样式。好的。

我建议对有符号的操作也编写和使用静态方法,因此在代码中不会看到有符号和无符号操作的运算符和静态方法的混合,除非代码中只需要有符号的操作,并且只使用运算符也可以。好的。

另外,我建议避免使用short、int和long原语类型,并分别使用word、dword和qword,您将要为无符号操作和/或有符号操作调用静态方法,而不是使用运算符。好的。

如果您将只执行带符号的操作,并且只在代码中使用运算符,那么可以使用这些基元类型short、int和long。好的。

实际上,语言中不存在word、dword和qword,但是您可以为每个类创建新类,并且每个类的实现应该非常容易:好的。

类字只保留基元类型short,类dword只保留基元类型int,类qword只保留基元类型long。现在,所有无符号和有符号的方法都是静态的或不是您所选择的,您可以在每个类中实现,即所有16位操作都是无符号的和有符号的,在word类上给出含义名称;所有32位操作都是无符号的和有符号的,在dword类上给出含义名称;所有64位操作都是无符号的和有符号的。d在Qword类上给出意义名称。好的。

如果你不喜欢给每种方法提供太多不同的名字,你可以在爪哇中使用重载,很好地读取Java也没有删除它!好的。

如果您想要方法而不是8位有符号操作的运算符,以及8位无符号操作的方法(根本没有运算符),那么您可以创建字节类(注意,第一个字母"b"是大写的,因此这不是基元类型byte),并实现此类中的方法。好的。

关于传递值和传递引用:好的。

如果我没有错,就像在C中一样,原语对象是按值自然传递的,而类对象是按引用自然传递的,这意味着类型为byte、word、dword和qword的对象将按引用传递,而不是按默认值传递。我希望Java的结构对象是C语言,因此,所有字节、单词、dword和qword都可以实现为结构,而不是类,因此默认情况下它们是通过值传递的,而不是默认引用的,就像C语言中的任何结构对象一样,原始类型通过值传递,而不是默认引用,但是因为Java比C语言更坏,我们必须处理它,然后在那里进行处理。仅为类和接口,默认情况下通过引用传递,而不是通过值传递。因此,如果您想通过值而不是引用来传递字节、word、dword和qWord对象,就像Java中的任何其他类对象一样,也在C语言中,则必须简单地使用复制构造函数,就是这样。好的。

这是我唯一能想到的解决办法。我只希望我可以将原始类型Type填充到Word、Dword和QWord中,但是Java既不支持Type,也不支持使用,不像支持使用的C,它相当于C的TyPulf。好的。

关于输出:好的。

对于相同的位序列,您可以用多种方式打印它们:二进制、十进制(如c printf中的%u含义)、八进制(如c printf中的%o含义)、十六进制(如c printf中的%x含义)和整数(如c printf中的%d含义)。好的。

注意,c printf不知道作为参数传递给函数的变量的类型,因此printf只知道从char*对象传递给函数的第一个参数的每个变量的类型。好的。

因此,在每个类中:byte、word、dword和qword,您可以实现print方法并获得printf的功能,即使类的基元类型是有符号的,您仍然可以通过执行一些涉及逻辑和移位操作的算法将其打印为无符号的,以便将数字打印到输出。好的。

不幸的是,我给你的链接没有显示如何实现这些打印方法,但我相信你可以谷歌的算法,你需要实现这些打印方法。好的。

我只能回答你的问题并建议你。好的。好啊。


因为以东1〔0〕型是纯粹的邪恶。

事实上,在c-unsigned - int中,产生unsigned更为邪恶。

下面是一个问题的快照,这个问题让我不止一次感到痛苦:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 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是无符号类型size_t,所以整个表达式n - (rays.size() - 1) / 2的计算结果为unsigned。该表达式是n射线中间的一个有符号位置:左边中间的第一条射线的位置为-1,右边的第一条射线的位置为+1等,取abs值乘以delta角,得到n射线和Th之间的角度。中间的一个。

不幸的是,对于我来说,上面的表达式包含了邪恶的无符号表达式,它的计算结果不是-1,而是2^32-1。随后转换为double的版本密封了这个错误。

在错误地使用unsigned算术导致一两个错误之后,人们必须开始怀疑自己得到的额外位是否值得额外的麻烦。我尽量避免在算术中使用unsigned类型,尽管它仍然用于二进制屏蔽等非算术运算。


我想一个不幸的附带效应。在Java的嵌入式数据库系统,数你可以有一个32位的ID字段是2^31 -1(2~32,价值20亿的困境,困境~40)。


我之所以这么做是因为他们太懒了,无法实施/纠正这个错误。建议C/C++程序员不理解无符号、结构、联合、位标志…只是荒谬而已。

你正在和一个BASH/BASH/Java程序员交谈,开始编程一个LAC,没有任何真正的知识,或者你只是在说自己的想法。;)

当你每天处理文件或硬件的格式时,你开始怀疑他们到底在想什么。

这里的一个好例子是尝试使用无符号字节作为自旋转循环。对于那些不理解最后一句话的人来说,你究竟是如何称自己为程序员的。

直流