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

发布于 2024-07-11 18:02:24 字数 208 浏览 7 评论 0原文

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

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

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

最后,在某些情况下,无符号整数对于某些运算(例如除法)可能更有效。

包括这些有什么缺点?

Why doesn't Java include support for unsigned integers?

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.

Lastly, in some cases, unsigned integers can be more efficient for certain operations, such as division.

What's the downside to including these?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(17

稍尽春風 2024-07-18 18:02:24

这是来自对 Gosling 和其他人的采访,关于简单性:

Gosling:对于我来说,作为一名语言设计师,我现在并不真正认为自己是这样,“简单”真正的最终含义是我是否可以期望 J. Random Developer 将规范牢记在心。 例如,这个定义表明,Java 就不是——事实上,许多这些语言最终都会出现很多极端情况,而没有人真正理解这些情况。 对任何 C 开发人员进行有关无符号的测验,很快您就会发现几乎没有 C 开发人员真正了解无符号的情况以及无符号算术是什么。 诸如此类的事情使 C 变得复杂。 我认为 Java 的语言部分非常简单。 您必须查找的库。

This is from an interview with Gosling and others, about simplicity:

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.

请远离我 2024-07-18 18:02:24

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

  • 一般来说,Java 设计者希望简化
  • 日常使用的数据类型的全部内容,他们认为最常见的需求是
  • 用于实现某些算法的有符号数据类型,无符号 数据类型有时需要算术,但是将实现此类算法的程序员也将具备“解决”使用带符号数据类型进行无符号算术的知识。

大多数情况下,我认为这是一个合理的决定。 可能,我会:

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

不过,尽管有一点拼凑,对高达 32 位的无符号值进行操作并不算太糟糕,而且大多数人不需要无符号64 位除法或比较。

Reading between the lines, I think the logic was something like this:

  • generally, the Java designers wanted to simplify the repertoire 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

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?)

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.

我不会写诗 2024-07-18 18:02:24

这是一个较老的问题,帕特确实简短地提到了 char,我只是想我应该为其他将来会看到这个问题的人扩展这个问题。 让我们仔细看看 Java 基本类型:

byte - 8 位有符号整数

short - 16 位有符号整数

int - 32-位有符号整数

long - 64 位有符号整数

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

尽管 char 不支持 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 是一个可行的选择。


编辑

JDK8 有新的 API Long< /code>Integer< /code>在将 longint 值视为无符号值时提供辅助方法。

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

此外,Guava 提供了许多辅助方法来执行类似的操作整数类型有助于缩小由于缺乏对无符号整数的本机支持而留下的空白。

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:

byte - 8-bit signed integer

short - 16-bit signed integer

int - 32-bit signed integer

long - 64-bit signed integer

char - 16-bit character (unsigned integer)

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 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.


Edit

With JDK8 there are new APIs for Long and Integer which provide helper methods when treating long and int values as unsigned values.

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

Additionally, Guava provides 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.

何时共饮酒 2024-07-18 18:02:24

Java 确实有无符号类型,或者至少有一种: char 是无符号短整型。 因此,无论高斯林提出什么借口,这实际上只是他对为什么没有其他未签名类型的无知。

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

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.

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.

下壹個目標 2024-07-18 18:02:24

一旦有符号和无符号整数混合在表达式中,事情就会开始变得混乱,您可能会丢失信息。 将 Java 限制为有符号整数只会真正解决问题。 我很高兴我不必担心整个签名/未签名的业务,尽管有时我确实会错过一个字节中的第 8 位。

As soon as signed and unsigned ints are mixed in an expression things start to get messy and you probably will lose 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.

阳光的暖冬 2024-07-18 18:02:24

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

这家伙说是因为 C 标准定义了涉及无符号和有符号整数的操作被视为无符号。 这可能会导致负有符号整数滚动到一个大的无符号整数,从而可能导致错误。

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.

终陌 2024-07-18 18:02:24

我认为 Java 本身就很好,添加 unsigned 会使它变得复杂而没有太多好处。
即使使用简化的整数模型,大多数 Java 程序员也不知道基本数字类型的行为方式 - 只需阅读这本书 Java Puzzlers 看看您可能存在哪些误解。

至于实用建议:

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

  • 仅当您需要节省空间时才对数组使用较小的类型。

  • 如果您正好需要 64/32/16/8 位,请使用 long/int/short/byte 并且不再担心符号位,除了除法、比较、右移和转换。

另请参阅这个关于“移植随机数”的答案从 C 到 Java 的生成器”。

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 Puzzlers to see what misconceptions you might hold.

As for practical advice:

  • If your values are somewhat arbitrary size and don't fit into int, use long.
    If they don't fit into long use BigInteger.

  • 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.

See also this answer about "porting a random number generator from C to Java".

余生再见 2024-07-18 18:02:24

我知道这篇文章太旧了; 不过,出于您的兴趣,在 Java 8 及更高版本中,您可以使用 int 数据类型来表示无符号 32 位整数,其最小值为 0,最大值为 2 32-1。 使用 Integer 类将 int 数据类型用作无符号整数以及静态方法,例如 compareUnsigned()divideUnsigned()Integer 类中添加了 code> 等,以支持无符号整数的算术运算。

I know this post is too old; however for your interest, in Java 8 and later, you can use the int data type to represent an unsigned 32-bit integer, which has a minimum value of 0 and a maximum value of 232−1. Use the Integer class to use int data type as an unsigned integer and static methods like compareUnsigned(), divideUnsigned() etc. have been added to the Integer class to support the arithmetic operations for unsigned integers.

淡莣 2024-07-18 18:02:24

我听说过这样的故事:它们将包含在原始 Java 版本附近。 Oak 是 Java 的前身,在一些规范文档中提到了无符号值。 不幸的是,这些从未进入 Java 语言。 据任何人所知,他们只是没有得到实施,可能是由于时间限制。

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.

还在原地等你 2024-07-18 18:02:24

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

尽管 Gosling 担心,但我们可能仍会看到 Java 中对无符号类型的完全支持。

With JDK8 it does have some support for them.

We may yet see full support of unsigned types in Java despite Gosling's concerns.

滥情空心 2024-07-18 18:02:24

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

很久以前,当内存有限并且处理器不能同时自动在 64 位上运行时,每个位都更重要,因此有符号字节或无符号字节或短路实际上更重要,并且显然是正确的设计决策。 如今,在几乎所有常规编程情况下,仅使用有符号 int 就足够了,如果您的程序确实需要使用大于 2^31 - 1 的值,那么您通常只需要 long 值。 一旦您开始使用长整型,就更难找出为什么不能使用 2^63 - 1 正整数的原因了。 每当我们使用 128 位处理器时,这个问题就更小了。

I once took a C++ course with someone on the C++ standards committee who implied that Java made the right decision to avoid having unsigned integers because (1) most programs that use unsigned integers can do just as well with signed integers and this is more natural in terms of how people think, and (2) using unsigned integers results in lots easy to create but difficult to debug issues such as integer arithmetic overflow and losing significant bits when converting between signed and unsigned types. If you mistakenly subtract 1 from 0 using signed integers it often more quickly causes your program to crash and makes it easier to find the bug than if it wraps around to 2^32 - 1, and compilers and static analysis tools and runtime checks have to assume you know what you're doing since you chose to use unsigned arithmetic. Also, negative numbers like -1 can often represent something useful, like a field being ignored/defaulted/unset while if you were using unsigned you'd have to reserve a special value like 2^32 - 1 or something similar.

Long ago, when memory was limited and processors did not automatically operate on 64 bits at once, every bit counted a lot more, so having signed vs unsigned bytes or shorts actually mattered a lot more often and was obviously the right design decision. Today just using a signed int is more than sufficient in almost all regular programming cases, and if your program really needs to use values bigger than 2^31 - 1, you often just want a long anyway. Once you're into the territory of using longs, it's even harder to come up with a reason why you really can't get by with 2^63 - 1 positive integers. Whenever we go to 128 bit processors it'll be even less of an issue.

漫雪独思 2024-07-18 18:02:24

Java 出于务实的原因放弃了“C”规范中的一些精华,但随着开发人员的需求(关闭等),它们正在慢慢回归。

我提到第一个是因为它与本次讨论相关; 指针值遵守无符号整数算术。 并且,与此线程主题相关的是,在 Java 的有符号世界中维护无符号语义的困难。

我猜想如果有人让 Dennis Ritchie 的另一个自我为 Gosling 的设计团队提供建议,他们会建议给 Signed 一个“无穷大零”,这样所有地址偏移请求都会首先添加其代数环大小以避免负值。

这样,向数组抛出的任何偏移量都不会生成 SEGFAULT。 例如,在一个封装类中,我将其称为需要无符号行为的双精度型 RingArray - 在“自旋转循环”上下文中:

// ...
// 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
// ...

上述 RingArray 永远不会从负索引中“获取”,即使恶意请求者试图这样做。 请记住,还有许多要求先前(负)索引值的合法请求。

注意:外部 %modulus 取消引用合法请求,而内部 %modulus 掩盖了比 -modulus 更负面的负数中的公然恶意。 如果这出现在 Java +..+9 || 中 8+..+ 规范,那么问题将真正成为“无法“自我旋转”故障的程序员”。

我相信所谓的Java unsigned int“缺陷”可以用上面的一句话来弥补。

PS:只是为了给上面的 RingArray 内务处理提供上下文,这里有一个候选“set”操作来匹配上面的“get”元素操作:

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
}

There's a few gems in the 'C' spec that Java dropped for pragmatic reasons but which are slowly creeping back with developer demand (closures, etc).

I mention a first one because it's related to this discussion; the adherence of pointer values to unsigned integer arithmetic. And, in relation to this thread topic, the difficulty of maintaining Unsigned semantics in the Signed world of Java.

I would guess if one were to get a Dennis Ritchie alter ego to advise Gosling's design team it would have suggested giving Signed's a "zero at infinity", so that all address offset requests would first add their ALGEBRAIC RING SIZE to obviate negative values.

That way, any offset thrown at the array can never generate a SEGFAULT. For example in an encapsulated class which I call RingArray of doubles that needs unsigned behaviour - in "self rotating loop" context:

// ...
// 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
// ...

The above RingArray would never ever 'get' from a negative index, even if a malicious requestor tried to. Remember, there are also many legitimate requests for asking for prior (negative) index values.

NB: The outer %modulus de-references legitimate requests whereas the inner %modulus masks out blatant malice from negatives more negative than -modulus. If this were to ever appear in a Java +..+9 || 8+..+ spec, then the problem would genuinely become a 'programmer who cannot "self rotate" FAULT'.

I'm sure the so-called Java unsigned int 'deficiency' can be made up for with the above one-liner.

PS: Just to give context to above RingArray housekeeping, here's a candidate 'set' operation to match the above 'get' element operation:

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
}
预谋 2024-07-18 18:02:24

因为 unsigned 类型是纯粹的邪恶。

事实上,在 C 中 unsigned - int 会产生 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 为无符号类型 size_t,因此整个表达式 n - (rays.size() - 1) / 2 的计算结果为 unsigned。 该表达式旨在成为中间第 n 条射线的有符号位置:左侧中间的第 1 条射线的位置为 -1,右边第一个的位置为 +1,等等。在获取绝对值并乘以 delta 角度后,我将得到第 n 条射线与中间射线之间的角度一。

不幸的是,对我来说,上面的表达式包含邪恶的无符号,并且不是计算为 -1,而是计算为 2^32-1。 随后转换为 double 解决了该错误。

在由于滥用无符号算术而导致一两个错误之后,人们必须开始怀疑是否值得为此付出额外的努力。 我正在尽可能避免在算术中使用无符号类型,尽管仍然将其用于非算术运算(例如二进制掩码)。

Because unsigned type is pure evil.

The fact that in C unsigned - int produces unsigned is even more evil.

Here is a snapshot of the problem that burned me more than once:

// 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 ...
}

Have you noticed the bug yet? I confess I only saw it after stepping in with the debugger.

Because n is of unsigned type size_t the entire expression n - (rays.size() - 1) / 2 evaluates as unsigned. That expression is intended to be a signed position of the nth ray from the middle one: the 1st ray from the middle one on the left side would have position -1, the 1st one on the right would have position +1, etc. After taking abs value and multiplying by the delta angle I would get the angle between nth ray and the middle one.

Unfortunately for me the above expression contained the evil unsigned and instead of evaluating to, say, -1, it evaluated to 2^32-1. The subsequent conversion to double sealed the bug.

After a bug or two caused by misuse of unsigned arithmetic one has to start wondering whether the extra bit one gets is worth the extra trouble. I am trying, as much as feasible, to avoid any use of unsigned types in arithmetic, although still use it for non-arithmetic operations such as binary masks.

凌乱心跳 2024-07-18 18:02:24

你的问题是“为什么Java不支持无符号整数”?

我对你问题的回答是,Java 想要所有的原始类型:bytecharshortint 和 long 应被视为 byteworddwordqword分别,就像在汇编中一样,Java 运算符是对除 char 之外的所有基本类型的有符号操作,但仅对 char 进行操作仅无符号 16 位。

因此,静态方法应该是 32 位和 64 位的无符号操作

您需要最终类,可以调用其静态方法来执行无符号操作。

您可以创建这个最终类,将其命名为您想要的任何名称并实现它的静态方法。

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

在我看来,Java 与 C++ 完全不相似,如果它既不支持无符号类型也不支持运算符重载,所以我认为 Java 应该被视为与 C++ 和 C 完全不同的语言。

顺便说一句,它的语言名称也完全不同。

所以我不建议在 Java 中键入类似于 C 的代码,我根本不建议键入类似于 C++ 的代码,因为那样在 Java 中你将无法执行接下来在 C++ 中要做的事情,也就是说,代码根本不会继续像 C++ 那样,对我来说,这样编码、改变中间的样式是不好的。

我建议也为签名操作编写和使用静态方法,这样您就不会在代码中看到签名和未签名操作的运算符和静态方法的混合,除非您只需要代码中的签名操作,并且可以仅使用运算符。

另外,我建议避免使用 shortintlong 原始类型,并使用 worddword分别是 qword,并且您将调用无符号操作和/或有符号操作的静态方法,而不是使用运算符。

如果您打算仅执行签名操作并仅在代码中使用运算符,那么可以使用这些基本类型 shortintlong< /强>。

实际上,worddwordqword 并不存在于该语言中,但是您可以为它们创建新类每个以及每个的实现都应该非常简单:

word 仅保存原始类型 short,类 dword 保存原始类型 <仅strong>int,类qword仅包含原始类型long。 现在,所有无符号和有符号方法都是静态或非静态的,您可以在每个类中实现,即通过在 word 类上给出含义名称来实现所有无符号和有符号的 16 位操作,所有通过在 dword 类上给出含义名称来进行无符号和有符号的 32 位操作,以及通过在 qword 类上给出含义名称来进行的所有 64 位操作(无论是无符号还是有符号)。

如果您不喜欢为每个方法提供太多不同的名称,您始终可以在 Java 中使用重载,很高兴看到 Java 也没有删除它!

如果您想要 8 位有符号运算的方法而不是运算符,以及根本没有运算符的 8 位无符号运算的方法,那么您可以创建 Byte 类(请注意,第一个字母“B”是大写,所以这不是原始类型byte)并实现此类中的方法。

关于按值传递和按引用传递:

如果我没记错的话,就像在 C# 中一样,原始对象自然是按值传递,但类对象自然是按引用传递,所以这意味着 Byteworddwordqword 默认情况下将通过引用传递,而不是通过值传递。 我希望 Java 能像 C# 一样拥有 struct 对象,
因此所有Byteworddwordqword都可以实现为struct而不是 class,因此默认情况下它们是按值传递的,而不是按引用传递的,就像 C# 中的任何结构体对象一样,像原始类型一样,默认情况下是按值传递而不是按引用传递,但是因为 Java 比 C# 更糟糕,我们必须处理这个问题,所以只有类和接口,它们默认通过引用传递,而不是通过值传递。 因此,如果您想按值而不是按引用传递 Byteworddwordqword 对象,例如对于 Java 和 C# 中的任何其他类对象,您只需使用复制构造函数即可。

这是我能想到的唯一解决方案。 我只是希望我可以将原始类型typedef为word、dword和qword,但是Java既不支持typedef也不支持using,不像C#支持using,这相当于C的typedef。

关于输出:

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

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

因此,在每个类中:Byteworddwordqword,您可以实现 print 方法并获取printf 的功能,即使类的原始类型是有符号的,您仍然可以通过遵循一些涉及逻辑和移位操作的算法来将其打印为无符号,以获得要打印到输出的数字。

不幸的是,我给您的链接没有显示如何实现这些打印方法,但我相信您可以通过谷歌搜索实现这些打印方法所需的算法。

这就是我能回答你的问题和建议你的全部。

Your question is "Why doesn't Java support unsigned ints"?

And my answer to your question is that Java wants that all of it's primitive types: byte, char, short, int and long should be treated as byte, word, dword and qword respectively, exactly like in assembly, and the Java operators are signed operations on all of it's primitive types except for char, but only on char they are unsigned 16 bit only.

So static methods suppose to be the unsigned operations also for both 32 and 64 bit.

You need final class, whose static methods can be called for the unsigned operations.

You can create this final class, call it whatever name you want and implement it's static methods.

If you have no idea about how to implement the static methods then this link may help you.

In my opinion, Java is not similar to C++ at all, if it neither support unsigned types nor operator overloading, so I think that Java should be treated as completely different language from both C++ and from C.

It is also completely different in the name of the languages by the way.

So I don't recommend in Java to type code similar to C and I don't recommend to type code similar to C++ at all, because then in Java you won't be able to do what you want to do next in C++, i.e. the code won't continue to be C++ like at all and for me this is bad to code like that, to change the style in the middle.

I recommend to write and use static methods also for the signed operations, so you don't see in the code mixture of operators and static methods for both signed and unsigned operations, unless you need only signed operations in the code, and it's okay to use the operators only.

Also I recommend to avoid using short, int and long primitive types, and use word, dword and qword respectively instead, and you are about call the static methods for unsigned operations and/or signed operations instead of using operators.

If you are about to do signed operations only and use the operators only in the code, then this is okay to use these primitive types short, int and long.

Actually word, dword and qword don't exist in the language, but you can create new class for each and the implementation of each should be very easy:

The class word holds the primitive type short only, the class dword holds the primitive type int only and the class qword holds the primitive type long only. Now all the unsigned and the signed methods as static or not as your choice, you can implement in each class, i.e. all the 16 bit operations both unsigned and signed by giving meaning names on the word class, all the 32 bit operations both unsigned and signed by giving meaning names on the dword class and all the 64 bit operations both unsigned and signed by giving meaning names on the qword class.

If you don't like giving too many different names for each method, you can always use overloading in Java, good to read that Java didn't remove that too!

If you want methods rather than operators for 8 bit signed operations and methods for 8 bit unsigned operations that have no operators at all, then you can create the Byte class (note that the first letter 'B' is capital, so this is not the primitive type byte) and implement the methods in this class.

About passing by value and passing by reference:

If I am not wrong, like in C#, primitive objects are passed by value naturally, but class objects are passed by reference naturally, so that means that objects of type Byte, word, dword and qword will be passed by reference and not by value by default. I wish Java had struct objects as C# has,
so all Byte, word, dword and qword could be implemented to be struct instead of class, so by default they were passed by value and not by reference by default, like any struct object in C#, like the primitive types, are passed by value and not by reference by default, but because that Java is worse than C# and we have to deal with that, then there is only classes and interfaces, that are passed by reference and not by value by default. So if you want to pass Byte, word, dword and qword objects by value and not by reference, like any other class object in Java and also in C#, you will have to simply use the copy constructor and that's it.

That's the only solution that I can think about. I just wish that I could just typedef the primitive types to word, dword and qword, but Java neither support typedef nor using at all, unlike C# that supports using, which is equivalent to the C's typedef.

About output:

For the same sequence of bits, you can print them in many ways: As binary, as decimal (like the meaning of %u in C printf), as octal (like the meaning of %o in C printf), as hexadecimal (like the meaning of %x in C printf) and as integer (like the meaning of the %d in C printf).

Note that C printf doesn't know the type of the variables being passed as parameters to the function, so printf knows the type of each variable only from the char* object passed to the first parameter of the function.

So in each of the classes: Byte, word, dword and qword, you can implement print method and get the functionality of printf, even though the primitive type of the class is signed, you still can print it as unsigned by following some algorithm involving logical and shift operations to get the digits to print to the output.

Unfortunately the link I gave you doesn't show how to implement these print methods, but I am sure you can google for the algorithms you need to implement these print methods.

That's all I can answer your question and suggest you.

寂寞陪衬 2024-07-18 18:02:24

我可以向你保证,Java 中确实没有必要使用无符号数。

以C为例。 让我们写一些类似的内容:

unsigned int num = -7;
printf("%d", num);

你能猜出打印的是什么吗?

-7

不存在真正的正整数这样的东西。 无符号整数只是一个 n 字节(取决于 C 中的体系结构)值,不分配 MSB 作为符号。 它不会检查分配或读取的数字的实际符号: https://www.gnu.org/s/libc/manual/html_node/Integers.html

I can assure you there is really no necessity for unsigned numbers in Java.

Take C for example. Let's write something like:

unsigned int num = -7;
printf("%d", num);

Can you guess what's printed?

-7

There's no such thing as a true positive integer. An unsigned integer is just an n-byte(depends on architecture in C) value that doesn't allocate the MSB for sign. It doesn't check for the actual sign of the number assigned or read: https://www.gnu.org/s/libc/manual/html_node/Integers.html

踏雪无痕 2024-07-18 18:02:24

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

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).

划一舟意中人 2024-07-18 18:02:24

恕我直言,原因是他们太懒了,无法实施/纠正该错误。
暗示 C/C++ 程序员不理解无符号、结构、联合、位标志......简直是荒谬的。

要么你正在与一个即将开始用 C 语言编程的 basic/bash/java 程序员交谈,但对这种语言没有任何真正的了解,或者你只是在凭自己的想法说话。 ;)

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

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

直流

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.

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. ;)

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文