意外的无限字节 for 循环

发布于 2024-09-28 05:50:07 字数 180 浏览 12 评论 0原文

我有以下循环:

for (byte i = 0 ; i < 128; i++) {
    System.out.println(i + 1 + " " + name);
}

当我执行程序时,它会在无限循环中打印从 -128 到 127 的所有数字。为什么会出现这种情况?

I have the following loop:

for (byte i = 0 ; i < 128; i++) {
    System.out.println(i + 1 + " " + name);
}

When I execute my programm it prints all numbers from -128 to 127 in an infinite loop. Why does this happen?

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

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

发布评论

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

评论(8

装纯掩盖桑 2024-10-05 05:50:07

byte 是 1 字节类型,因此可以在 -128...127 之间变化,因此条件 i < 128 始终为真。当你将 1 加到 127 时,它会溢出并变成 -128,依此类推(无限)循环......

byte is a 1-byte type so can vary between -128...127, so condition i < 128 is always true. When you add 1 to 127 it overflows and becomes -128 and so on in a (infinite) loop...

半﹌身腐败 2024-10-05 05:50:07

127之后,当它递增时,它将变成-128,所以你的条件将不匹配。

bytebyte 数据类型是 8 位有符号二进制补码整数。它的最小值为 -128,最大值为 127(含)。 byte 数据类型对于节省大型数组中的内存非常有用,而内存节省实际上很重要。它们还可以用来代替 int,它们的限制有助于阐明您的代码;变量的范围是有限的,这一事实可以作为一种文档形式。


它的工作方式如下:

0, 1, 2, ..., 126, 127, -128, -127, ...

8 位可以表示最多 127 个有符号数字。

请参阅 此处了解原始数据类型。


图片胜于雄辩
替代文本

After 127, when it increments, it will become -128, so your condition won't match .

byte: The byte data type is an 8-bit signed two's complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive). The byte data type can be useful for saving memory in large arrays, where the memory savings actually matters. They can also be used in place of int where their limits help to clarify your code; the fact that a variable's range is limited can serve as a form of documentation.


It will work like this:

0, 1, 2, ..., 126, 127, -128, -127, ...

as 8 bits can represent a signed number up to 127.

See here for the primitive data types.


Picture says more than words
alt text

第七度阳光i 2024-10-05 05:50:07

因为字节在 Java 中是有符号的,所以它们总是小于 128。

为什么 Java 选择有符号字节是一个从古至今的谜团。我一直无法理解为什么他们破坏了一个完美的无符号数据类型:-)

试试这个:

for (byte i = 0 ; i >= 0; ++i ) {

或者,更好的是:

for (int i = 0 ; i < 128; ++i ) {

Because bytes are signed in Java so they will always be less than 128.

Why Java chose signed bytes is a mystery from the depths of time. I've never been able to understand why they corrupted a perfectly good unsigned data type :-)

Try this instead:

for (byte i = 0 ; i >= 0; ++i ) {

or, better yet:

for (int i = 0 ; i < 128; ++i ) {
晨曦÷微暖 2024-10-05 05:50:07

因为当 i == 127 并且执行 i++ 时,它会溢出到 -128。

because when i == 127 and and you executes i++ it overflows to -128.

薄荷港 2024-10-05 05:50:07

类型字节的范围为-128..127。所以i总是小于128。

The type byte has a range of -128..127. So i is always less than 128.

指尖上得阳光 2024-10-05 05:50:07

好吧,这背后的原因已经得到解答,但如果您对一些背景感兴趣:

是计算机可以识别的最小存储单位(注意不是最小的数字)。位要么是0,要么是1

字节是一种8位数据类型,这意味着它由8位字符串组成,例如101010100001110。使用简单的组合,我们知道有 2^8 = 256 可能的字节组合。

如果我们只想表示正数,我们可以直接从基数 2 转换为基数 10。工作方式是,对于位字符串 b7b6b5b4b3b2b1b0 ,十进制数为 dec = (bn * 2^n) 的 n=0 到 7 的总和。

通过仅表示正数(无符号字节),我们可以表示 0255(含)范围内的 256 个可能的数字。

当我们想要表示签名数据时,问题就出现了。一种简单的方法(注意,这是用于背景,而不是 java 的方式)是取最左边的位并将其设为符号位,其中 1 为负数,0是积极的。例如,00010110 将是 2110010110 将是 -21

这种系统有两个主要问题。首先是00000000010000000-0,但是众所周知,没有< code>-0 与 0 有所不同,但这样的系统允许数字和 0 ≠ -0。第二个问题是,由于表示两个零,系统只允许表示-127127之间的数字,范围只有254 (比以前少 2)。

一种更好的系统(也是大多数系统使用的系统)称为Two's Compliment。在二进制补码中,正数用其正常位串表示,其中最左边的位为 0。负数用最左边的位表示为 1,然后计算该数字的二进制补码(系统由此得名) )

虽然从数学上来说这是一个稍微复杂的过程,但因为我们正在处理数字2,所以有一些捷径。本质上,您可以采用正数版本并(从右到左)取所有零,直到达到 1。复制这些零和一,然后取其余位的 NOT。例如,要得到 -21,正 2100010110,我们采用 10 而不是其余的得到11101010-21的两个补码表示。

Two's Compliment 是一个更难掌握的系统,但它避免了前面提到的问题,并且 n 位数字可以表示从 -2^(n-1)的所有数字2^(n-1)-1 对于我们的字节来说意味着 -128127 (因此这个问题中存在问题)

一些注意事项:< br>
- 这仅适用于整数表示。实数表示完全是另一个系统(如果有要求,我相信我们可以在 CW 帖子中制作数字表示)
- 如果您有兴趣,维基百科还有更多数字表示系统。

Alright, so the reason behind this has been answered already, but in case you were interested in some background:

A bit is the smallest unit of storage which the computer can recognize (n.b. not the smallest number). A bit is either a 0 or a 1.

A byte is an 8 bit data type, meaning it is composed of 8 bit strings such as 10101010 or 0001110. Using simple combinatorics, we know that there are 2^8 = 256 possible combinations of bytes.

If we wanted to only represent positive numbers, we could do a straight conversion from base 2 to base 10. The way that works is, for a bit string b7b6b5b4b3b2b1b0 the number in decimal is dec = sum from n=0 to 7 of (bn * 2^n).

By only representing positive numbers ( an unsigned byte) we can represent 256 possible numbers in the range 0 to 255 inclusive.

The problem comes in when we want to represent signed data. A naive approach (n.b. this is for background, not the way java does it) is to take the left most bit and make it the sign bit where 1 is negative and 0 is positive. So for example 00010110 would be 21 and 10010110 would be -21.

There are two major problems with such a system. The first is that 00000000 is 0 and 10000000 is -0, but as everyone knows, there is no -0 that is somehow different from 0, but such a system allows for the number and 0 ≠ -0. The second problem is that, due to representing two zeroes, the system only allows for representing numbers from -127 to 127, a range of only 254 (2 less than before).

A much better system (and the one which most systems use) is called Two's Compliment. In Two's Compliment, the positive numbers are represented with their normal bit string where the leftmost bit is 0. Negative numbers are represented with the left most bit as a 1 and then calculating the two's compliment for that number (from whence the system gets its name)

Although mathematically it is a slightly more complex process, because we are dealing with the number 2 there are some short cuts. Essentially, you can take the positive version and (from right to left) take all zeroes until you hit a 1. Copy those zeroes and one, then take the NOT of the rest of the bits. So for example, to get -21, positive 21 is 00010110 we take the 10 and not the rest to get 11101010, the two's compliment representation of -21.

Two's Compliment is a much more difficult system to grasp, but it avoids the previously stated problems, and for an n-bit number can represent all digits from -2^(n-1) to 2^(n-1)-1 which for our byte means -128 to 127 (hence the problem in this question)

A couple of notes:
- This is for integer representation only. Real number representation is another system entirely (if there is a request for it, I'm sure we could make a number representation CW post)
- Wikipedia has a couple more number representation systems if you're interested.

几味少女 2024-10-05 05:50:07

最好的是如果你这样做

for (byte i = 0 ; i < Byte.MAX_VALUE; i++ ) {
  System.out.println( i + 1 + " " + name );
}

Best is if you do

for (byte i = 0 ; i < Byte.MAX_VALUE; i++ ) {
  System.out.println( i + 1 + " " + name );
}
冷弦 2024-10-05 05:50:07

这应该有效

        for (byte i = 0 ; i<128; ++i ) {
        if(i==-128)
            break;
        System.out.println( i + 1 + " " + "name" );
    }

this should work

        for (byte i = 0 ; i<128; ++i ) {
        if(i==-128)
            break;
        System.out.println( i + 1 + " " + "name" );
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文