为什么';Java支持无符号整数吗?

为什么';Java支持无符号整数吗?,java,language-design,unsigned,integer,Java,Language Design,Unsigned,Integer,为什么Java不支持无符号整数 在我看来,这似乎是一个奇怪的遗漏,因为它们允许编写不太可能在意外的大输入上产生溢出的代码 此外,使用无符号整数可以是一种自我记录的形式,因为它们表明无符号整数要保存的值永远不应该是负数 最后,在某些情况下,无符号整数对于某些操作(如除法)更有效 包含这些内容的缺点是什么? 这家伙说,因为C标准将涉及无符号和有符号整数的操作定义为无符号。这可能会导致负有符号整数转为大的无符号整数,可能会导致错误。这是一篇关于简单性的文章: 高斯林:作为一名语言设计师,我现在并不认为

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

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

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

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

包含这些内容的缺点是什么?

这家伙说,因为C标准将涉及无符号和有符号整数的操作定义为无符号。这可能会导致负有符号整数转为大的无符号整数,可能会导致错误。

这是一篇关于简单性的文章:

高斯林:作为一名语言设计师,我现在并不认为自己是语言设计师,“简单”最终的真正含义是,我能指望J.Random Developer将规范牢记在脑中吗。这个定义说,举例来说,Java并不是——事实上,这些语言中的很多最终都会出现很多没有人真正理解的情况。对任何C开发人员进行无符号测试,很快你就会发现几乎没有C开发人员真正了解无符号的情况,什么是无符号算术。这样的事情使C变得复杂。我认为Java的语言部分相当简单。你必须查的图书馆


我听说它们将被包含在原始Java版本的附近。Oak是Java的前身,在一些规范文档中提到了usigned值。不幸的是,这些都没有进入Java语言。据任何人所知,它们只是没有得到实现,可能是由于时间限制。

一旦表达式中混合了有符号和无符号整数,事情就会变得一团糟,您可能会丢失信息。将Java限制为已签名的整数只会真正清除问题。我很高兴我不必担心整个签名/未签名的业务,尽管我有时会遗漏字节中的第8位。

从字里行间看,我认为逻辑是这样的:

  • 通常,Java设计人员希望简化可用的数据类型
  • 对于日常用途,他们认为最常见的需求是有符号的数据类型
  • 为了实现某些算法,有时需要使用无符号算术,但实现此类算法的程序员也应该具备使用有符号数据类型执行无符号算术的知识
大多数情况下,我认为这是一个合理的决定。我可能会:

  • 使字节无符号,或者至少为这一数据类型提供了有符号/无符号的备选方案,可能具有不同的名称(使其有符号有利于一致性,但何时需要有符号字节?)
  • 取消“short”(上次使用16位有符号算术是什么时候?)

尽管如此,有了一点麻烦,对高达32位的无符号值的操作也不是很糟糕,而且大多数人不需要无符号64位除法或比较。

我认为Java是可以的,添加无符号值会使它复杂化,但没有太多好处。 即使使用简化的整数模型,大多数Java程序员也不知道基本的数字类型是如何工作的——只需阅读这本书,看看您可能持有哪些误解

至于实际建议:

  • 如果您的值有点任意大小,并且不适合
    int
    ,请使用
    long
    。 如果它们不适合
    long
    使用
    biginger

  • 当需要节省空间时,仅对阵列使用较小的类型

  • 如果您恰好需要64/32/16/8位,请使用
    long
    /
    int
    /
    short
    /
    /
    字节
    并停止担心符号位,除法、比较、右移和强制转换除外


另请参见关于“将随机数生成器从C移植到Java”的回答。

我可以想到一个不幸的副作用。在java嵌入式数据库中,32位id字段的id数是2^31,而不是2^32(~20亿,而不是~40亿)。

java确实有无符号类型,或者至少有一个:char是无符号的缩写。所以,不管高斯林提出什么借口,其实都是因为他不知道为什么没有其他的无符号类型


此外,短片类型:短片一直用于多媒体。原因是您可以在一个32位无符号长文件中放入2个样本,并对许多操作进行矢量化。8位数据和无符号字节也是如此。你可以在一个寄存器中放入4或8个样本进行矢量化。

这是一个较老的问题,pat确实简要地提到了char,我只是想我应该为以后会看到这一点的其他人扩展一下。让我们仔细看看java原语类型:

字节
-8位有符号整数

short
-16位有符号整数

int
-32位有符号整数

long
-64位有符号整数

char
-16位字符(无符号整数)

虽然
char
不支持
unsigned
算术,但它基本上可以被视为
unsigned
整数。您必须显式地将算术运算转换回
char
,但它确实提供了一种指定
无符号
数字的方法

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是一个好办法
// 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 ...
}
// ...
// Housekeeping state variable
long entrycount;     // A sequence number
int cycle;           // Number of loops cycled
int size;            // Active size of the array because size<modulus during cycle 0
int modulus;         // Maximal size of the array

// Ring state variables
private int head;   // The 'head' of the Ring
private int tail;   // The ring iterator 'cursor'
// tail may get the current cursor position
// and head gets the old tail value
// there are other semantic variations possible

// The Array state variable
double [] darray;    // The array of doubles

// somewhere in constructor
public RingArray(int modulus) {
    super();
    this.modulus = modulus;
    tail =  head =  cycle = 0;
    darray = new double[modulus];
// ...
}
// ...
double getElementAt(int offset){
    return darray[(tail+modulus+offset%modulus)%modulus];
}
//  remember, the above is treating steady-state where size==modulus
// ...
void addElement(long entrycount,double value){ // to be called only by the keeper of entrycount
    this.entrycount= entrycount;
    cycle = (int)entrycount/modulus;
    if(cycle==0){                       // start-up is when the ring is being populated the first time around
        size = (int)entrycount;         // during start-up, size is less than modulus so use modulo size arithmetic
        tail = (int)entrycount%size;    //  during start-up
    }
    else {
        size = modulus;
        head = tail;
        tail = (int)entrycount%modulus; //  after start-up
    }
    darray[head] = value;               //  always overwrite old tail
}