Неожиданный бесконечный байт для цикла - PullRequest
34 голосов
/ 20 октября 2010

У меня есть следующий цикл:

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

Когда я выполняю свою программу, она печатает все числа от -128 до 127 в бесконечном цикле.Почему это происходит?

Ответы [ 8 ]

79 голосов
/ 20 октября 2010

байт является однобайтовым типом, поэтому может варьироваться от -128 до 127, поэтому условие i <128 всегда выполняется. Когда вы добавляете от 1 до 127, он переполняется и становится -128 и так далее в (бесконечном) цикле ... </p>

20 голосов
/ 20 октября 2010

После 127, когда оно увеличивается, оно становится -128, поэтому ваше состояние не будет соответствовать.

байт : тип данных byte представляет собой 8-разрядное целое число со знаком в виде двоичного числа со знаком. Минимальное значение -128 и максимальное значение 127 (включительно). Тип данных byte может быть полезен для сохранения памяти в больших массивах, где экономия памяти действительно имеет значение. Их также можно использовать вместо int, где их пределы помогают уточнить ваш код; тот факт, что диапазон переменной ограничен, может служить формой документации.


Это будет работать так:

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

как 8 битов может представлять число со знаком до 127.

См. здесь для примитивных типов данных.


Изображение говорит больше, чем слова alt text

11 голосов
/ 20 октября 2010

Поскольку байты подписаны в Java, они будут всегда меньше 128.

Почему Java выбрала подписанные байты - загадка глубины времени. Я никогда не мог понять, почему они испортили совершенно хороший тип данных без знака: -)

Попробуйте вместо этого:

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

или, еще лучше:

for (int i = 0 ; i < 128; ++i ) {
7 голосов
/ 20 октября 2010

потому что когда я == 127 и вы выполняете i ++, он переполняется до -128.

6 голосов
/ 20 октября 2010

Тип байта имеет диапазон -128..127. Так что i всегда меньше 128.

3 голосов
/ 04 ноября 2010

Хорошо, поэтому причина этого уже была решена, но на случай, если вас заинтересовал какой-то фон:

A bit - это наименьшая единица памяти, которую может распознать компьютер (например, не наименьшее число). Бит это либо 0, либо 1.

A byte - это 8-битный тип данных, то есть он состоит из 8-битных строк, таких как 10101010 или 0001110. Используя простую комбинаторику, мы знаем, что существует 2^8 = 256 возможных комбинаций байтов.

Если бы мы хотели представлять только положительные числа, мы могли бы выполнить прямое преобразование из базы 2 в базу 10. Это работает для битовой строки b7b6b5b4b3b2b1b0, число в десятичной дроби равно dec = sum from n=0 to 7 of (bn * 2^n).

Представляя только положительные числа (unsigned byte), мы можем представить 256 возможных чисел в диапазоне от 0 до 255 включительно.

Проблема возникает, когда мы хотим представить подписанные данные. Наивный подход (н.б. это для фона, а не для java) - взять самый левый бит и сделать его знаковым битом, где 1 отрицательно, а 0 положительно. Так, например, 00010110 будет 21, а 10010110 будет -21.

Есть две основные проблемы с такой системой. Во-первых, 00000000 - это 0, а 10000000 - это -0, но, как все знают, нет -0, который каким-то образом отличается от 0, но такая система учитывает число и 0 ≠ -0. Вторая проблема заключается в том, что из-за представления двух нулей система допускает только представление чисел от -127 до 127, диапазон которых составляет всего 254 (2 меньше, чем прежде).

Гораздо лучшая система (и та, которую использует большинство систем) называется Two's Compliment . В комплименте Two положительные числа представлены их обычной строкой битов, где крайний левый бит равен 0. Отрицательные числа представлены самым левым битом как 1, а затем вычисляется комплимент двоих для этого числа (откуда система получает свое имя )

Хотя математически это немного более сложный процесс, потому что мы имеем дело с числом 2, но есть несколько коротких путей. По сути, вы можете взять положительную версию и (справа налево) взять все нули, пока не достигнете 1. Скопируйте эти нули и один, а затем возьмите NOT оставшихся битов. Так, например, чтобы получить -21, положительное 21 равно 00010110, мы берем 10, а не остальное, чтобы получить 11101010, комплимент для двух -21.

Compliment Two - гораздо более сложная для понимания система, но она позволяет избежать ранее заявленных проблем и для n-битного числа может представлять все цифры от -2^(n-1) до 2^(n-1)-1, что для нашего байта означает от -128 до 127 (отсюда и проблема в этом вопросе)

Пара заметок:
- Это только для целочисленного представления. Представление действительных чисел - это совсем другая система (если есть запрос, я уверен, что мы могли бы сделать сообщение о числовом представлении CW)
- В Википедии есть еще пара систем представления чисел, если вам интересно.

2 голосов
/ 20 октября 2010

Лучше всего, если вы сделаете

for (byte i = 0 ; i < Byte.MAX_VALUE; i++ ) {
  System.out.println( i + 1 + " " + name );
}
1 голос
/ 20 октября 2010

это должно работать

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