Как целые числа, представленные внутри на уровне Java на уровне бит?

Я пытаюсь понять, как Java хранит целое число внутри. Я знаю, что все java-примитивные целые числа подписаны (кроме коротких?). Это означает, что для байта доступно меньше бит в байтах.

Мой вопрос: все ли целые числа (положительные и отрицательные) хранятся как два дополнения или являются только отрицательными числами в двух дополнениях?

Я вижу, что спецификации говорят x bit two complement number. Но я часто путаюсь.

Например:

  int x = 15; // Stored as binary as is?  00000000 00000000 00000000 00001111?
  int y = -22; // Stored as two complemented value? 11111111 11111111 11111111 11101010

Edit

Чтобы быть ясным, x = 15

   In binary as is: `00000000 00000000 00000000 00001111'
  Two complement: `11111111 11111111 11111111 11110001`

Итак, если ваш ответ all, цифры сохраняются как два дополнения, а затем:

  int x = 15; // 11111111 11111111 11111111 11110001
  int y = -22 // 11111111 11111111 11111111 11101010

Смятение здесь снова означает, что знак говорит, что оба являются отрицательными числами. Может быть, я неправильно понимаю/не понимаю?

Edit Не уверен, что мой вопрос запутан. Вынужден, чтобы изолировать вопрос:

Мой вопрос точно: положительные числа хранятся в binary as is, а отрицательные числа сохраняются как two complement?

Некоторые говорят, что все хранятся в двух дополнениях, и один ответ говорит, что только отрицательные числа хранятся как два дополнения.

Ответ 1

Давайте начнем с обобщения примитивных типов данных Java:

byte: тип данных байта - это 8-разрядное подписанное целое число из двух дополнений.

Короткая. Короткие данные - это 16-разрядное подписанное целое число из двух дополнений.

int: Тип данных Int - это 32-разрядное подписанное целое число из двух дополнений.

long: Длинный тип данных - это 64-разрядное подписанное целое число из двух дополнений.

float: Тип данных Float - это плавающая точка с плавающей точкой IEEE 754 с одной точностью .

double: двойной тип данных представляет собой двунаправленную 64-битную плавучую точку IEEE 754.

boolean: тип данных boolean представляет один бит информации.

char: char тип данных является <сильным > единственным 16-разрядным символом Unicode.

Источник

Два дополнения

"Хорошим примером является wiki, что связь с двумя дополнениями реализуется, отмечая, что 256 = 255 + 1 и ( 255 - x) является дополнением к x

0000 0111 = 7 два дополнения: 1111 1001 = -7

способ, которым он работает, - msb (старший бит) получает отрицательное значение, поэтому в случае выше

-7 = 1001 = -8 + 0+ 0+ 1

Положительные целые числа обычно хранятся как простые двоичные числа (1 равно 1, 10 равно 2, 11 равно 3 и т.д.).

Отрицательные целые числа сохраняются как два дополнения их абсолютного значения. Два дополнения положительного числа при использовании этих обозначений имеют отрицательное число.

Источник

Поскольку я получил несколько баллов за этот ответ, я решил добавить его в дополнительную информацию.

Более подробный ответ:

Среди других есть четыре основных подхода к представлению положительных и отрицательных чисел в двоичном формате, а именно:

  • Подписанная величина
  • Одно дополнение
  • Два дополнения
  • Уклон

1. Подписанная величина

Использует самый старший бит для представления знака, остальные биты используются для представления абсолютного значения. Где 0 представляет положительное число и 1 представляет отрицательное число, пример:

1011 = -3
0011 = +3

Это представление проще. Однако вы не можете добавлять двоичные числа так же, как вы добавляете десятичные числа, что затрудняет реализацию на аппаратном уровне. Более того, этот подход использует два бинарных шаблона для представления 0, 100... 0 и 0.... 0.

2. Одно дополнение

В этом представлении мы инвертируем все биты заданного числа, чтобы узнать его дополнение. Например:

010 = 2, so -2 = 101 (inverting all bits).

Проблема этого представления состоит в том, что все еще существуют два битовых шаблона для представления 0 (00..0 и 11..1)

3. Два дополнения

Чтобы найти отрицательный номер числа, в этом представлении мы инвертируем все биты, а затем добавим один бит. Добавление одного бита решает проблему наличия двух битовых шаблонов, представляющих 0. В этом представлении мы имеем только один (00... 0).

Например, мы хотим найти двоичное отрицательное представление 4 (десятичное) с использованием 4 бит. Сначала мы преобразуем 4 в двоичный:

4 = 0100

то мы инвертируем все биты

0100 -> 1011

наконец добавим один бит

1011 + 1 = 1100.

Итак, 1100 эквивалентно -4 в десятичной форме, если мы используем двоичное представление Two Complement с 4 битами.

Более быстрый способ найти дополнительный - это зафиксировать первый бит, который как значение 1 и инвертирование оставшихся битов. В приведенном выше примере это будет примерно так:

0100 -> 1100
^^ 
||-(fixing this value)
|--(inverting this one)

Два представления Complement, помимо наличия только одного представления для 0, также добавляет два двоичных значения таким же образом, что и в десятичных четных числах с разными знаками. Тем не менее, необходимо проверить случаи переполнения.

4. Уклон

Это представление используется для представления экспоненты в норме IEEE 754 для плавающих точек. Преимущество состоит в том, что двоичное значение со всеми битами до нуля представляет наименьшее значение. И двоичное значение со всеми битами до 1 представляет наибольшее значение. Как видно из названия, значение кодируется (положительное или отрицательное) в двоичном формате с n битами с смещением (обычно 2 ^ (n-1) или 2 ^ (n-1) -1).

Итак, если мы используем 8 бит, значение 1 в десятичной форме представлено в двоичном формате с использованием смещения 2 ^ (n-1), на значение:

+1 + bias = +1 + 2^(8-1) = 1 + 128 = 129
converting to binary
1000 0001

Ответ 2

Целочисленные числа Java имеют 32 бита и всегда подписываются. Это означает, что старший бит (MSB) работает как бит знака. Целое число, представленное int, представляет собой не что иное, как взвешенную сумму бит. Весы назначаются следующим образом:

Bit#    Weight
31      -2^31
30       2^30
29       2^29
...      ...
2        2^2
1        2^1
0        2^0

Обратите внимание, что вес MSB отрицательный (на самом деле самый большой отрицательный результат), поэтому, когда этот бит включен, все число (взвешенная сумма) становится отрицательным.

Пусть имитирует его с 4-битными номерами:

Binary    Weighted sum            Integer value
0000       0 + 0 + 0 + 0           0
0001       0 + 0 + 0 + 2^0         1
0010       0 + 0 + 2^1 + 0         2
0011       0 + 0 + 2^1 + 2^0       3
0100       0 + 2^2 + 0 + 0         4
0101       0 + 2^2 + 0 + 2^0       5
0110       0 + 2^2 + 2^1 + 0       6
0111       0 + 2^2 + 2^1 + 2^0     7 -> the most positive value
1000      -2^3 + 0 + 0 + 0        -8 -> the most negative value
1001      -2^3 + 0 + 0 + 2^0      -7
1010      -2^3 + 0 + 2^1 + 0      -6
1011      -2^3 + 0 + 2^1 + 2^0    -5
1100      -2^3 + 2^2 + 0 + 0      -4
1101      -2^3 + 2^2 + 0 + 2^0    -3
1110      -2^3 + 2^2 + 2^1 + 0    -2
1111      -2^3 + 2^2 + 2^1 + 2^0  -1

Итак, две вещи дополнения не являются исключительной схемой для представления отрицательных целых чисел, скорее мы можем сказать, что двоичное представление целых чисел всегда одно и то же, мы просто отрицаем вес самого значимого бита. И этот бит определяет знак целого.

В C есть ключевое слово unsigned (недоступно в java), которое можно использовать для объявления unsigned int x;. В целых числах без знака вес MSB является положительным (2^31), а не отрицательным. В этом случае диапазон unsigned int составляет от 0 до 2^32 - 1, а int имеет диапазон от -2^31 до 2^31 - 1.

С другой точки зрения, если вы рассматриваете два дополнения x как ~x + 1 (NOT x plus one), здесь объяснение:

Для любого x, ~x является просто побитовым обратным к x, поэтому везде, где x имеет 1 -бит, ~x будет иметь 0 -bit там (и наоборот) Versa). Итак, если вы их добавите, в добавлении не будет переноса, и сумма будет просто целым числом, каждый бит которого равен 1.

Для 32-разрядных целых чисел:

x + ~x = 1111 1111 1111 1111 1111 1111 1111 1111
x + ~x + 1 =   1111 1111 1111 1111 1111 1111 1111 1111 + 1
           = 1 0000 0000 0000 0000 0000 0000 0000 0000

Самый левый 1 -bit будет просто отброшен, так как он не подходит для 32-битного (целочисленного переполнения). Таким образом,

x + ~x + 1 = 0
-x = ~x + 1

Итак, вы можете видеть, что отрицательный x может быть представлен ~x + 1, который мы называем двумя дополнениями к x.

Ответ 3

Я пропустил следующую программу, чтобы узнать ее

public class Negative {
    public static void main(String[] args) {
        int i =10;
        int j = -10;

        System.out.println(Integer.toBinaryString(i));
        System.out.println(Integer.toBinaryString(j));
    }
}

Выход

1010
11111111111111111111111111110110

Из вывода кажется, что он использовал два дополнения.

Ответ 4

Согласно этот документ, все целые числа подписаны и сохранены в двух дополнительных форматах для java. Не уверен в его надежности.

Ответ 5

Oracle предоставляет некоторую документацию относительно Java Datatypes, которая может показаться интересной. В частности:

int: Тип данных int - это 32-битное подписанное целое число из двух дополнений. Он имеет минимальное значение -2147,483,648 и максимальное значение 2,147,483,647 (включительно).

Btw, short также сохраняется как два дополнения.

Ответ 6

Самый старший бит (32nd) указывает, что число положительное или отрицательное. Если оно равно 0, это означает, что число положительное и хранится в его фактическом двоичном представлении. но если оно равно 1, это означает, что число отрицательно и хранится в двух его представлениях. Поэтому, когда мы даем вес -2 ^ 32 на 32-й бит при восстановлении целочисленного значения из его двоичного представления, мы получаем фактический ответ.

Ответ 7

Спасибо, dreamcrash для ответа fooobar.com/questions/55486/...; на странице wiki они приводят пример, который помог мне понять, как узнать двоичное представление отрицательного аналога положительного числа.

Например, используя 1 байт (= 2 nibbles = 8 бит), десятичное число 5 представлен

0000 01012 Самый старший бит равен 0, поэтому шаблон представляет собой неотрицательное значение. Чтобы преобразовать в -5 в двухзначном дополнении, бит инвертированы; 0 становится 1, а 1 становится 0:

1111 1010 В этот момент цифра является дополнением к десятичное значение -5. Чтобы получить два дополнения, 1 добавляется к результат:

1111 1011 Результатом является подписанное двоичное число, представляющее десятичное значение -5 в форме с двумя дополнениями. Самый старший бит 1, поэтому представленное значение отрицательное.

Ответ 8

положительные числа хранятся непосредственно как двоичные. Для отрицательных чисел требуется 2 комплимента.

например:

15: 00000000 00000000 00000000 00001111
-15: 11111111 11111111 11111111 11110001

вот разница в бит бит.

Ответ 9

Положительные числа сохраняются/извлекаются как есть.

e.g) For +ve number 10; byte representation will be like 0-000 0010 
                                               (0 - MSB will represent that it is +ve).
So while retrieving based on MSB; it says it is +ve, 
so the value will be taken as it is. 

Но отрицательные числа будут сохранены после 2 дополнений (кроме MSB), а бит MSB будет установлен в 1.

например) при хранении -10, затем

  0-000 0010  -> (1 complement) -> 0-111 1101 
              -> (2 complement) 0-111 1101 + 1 -> 0-111 1110
  Now MSB will be set to one, since it is negative no -> 1-111 1110

при поиске, он обнаружил, что MSB установлен в 1. Таким образом, это отрицательный нет. И 2 дополнения будут выполнены иначе, чем MSB.

  1-111 1110  --> 1-000 0001 + 1 --> 1-000 0010
  Since MSB representing this is negative 10 --> hence  -10 will be retrived.

Casting

Также обратите внимание, что при запуске int/short to byte будет учитываться только последний байт вместе с последним байтом MSB,

Сделайте пример "-130" коротким, он может быть сохранен, как показано ниже

(MSB)1-(2 complement of)130(1000 0010) --> 1-111 1111 0111 1110

Теперь байтовое кастинг взял последний байт, который равен 0111 1110. (0-MSB) Поскольку MSB говорит, что это + ve значение, поэтому оно будет принято как есть. Это 126. (+ ve).

Возьмите другой пример "130", он может быть сохранен, как показано ниже

  0-000 000 1000 0010     (MSB = 0)

Теперь байтовое кастинг взял последний байт, который составляет 1000 0010. (1 = MSB) Поскольку MSB говорит, что это значение -ve, будет выполнено 2 дополнения, и будет возвращено отрицательное число. Таким образом, в этом случае -126 будет возвращено.

 1-000 0010  -> (1 complement) -> 1-111 1101 
             -> (2 complement) 1-111 1101 + 1 -> 1-111 1110 -> (-)111 1110
               = -126

Diff между (int) (char) (байт) -1 AND (int) (короткий) (байт) -1

(byte)-1       -> 0-000 0001 (2 Comp) -> 0-111 1111 (add sign) -> 1-111 1111
(char)(byte)-1 -> 1-111 1111 1111 1111  (sign bit is carry forwarded on left) 

аналогично

(short)(byte)-1-> 1-111 1111 1111 1111  (sign bit is carry forwarded on left) 

Но

(int)(char)(byte)-1 -> 0-0000000 00000000 11111111 11111111  = 65535
since char is unsigned; MSB won't be carry forwarded. 

и

(int)(Short)(byte)-1 -> 1-1111111 11111111 11111111 11111111 = -1
since short is signed; MSB is be carry forwarded. 

Ссылки

Почему два компонента используются для представления отрицательных чисел?

Что такое "дополнение 2" ?

Ответ 10

Для положительного целого значения 2'компонента совпадает с битом MSB 0 (like +14 2'complement is 01110).

Только для отрицательного целого числа мы вычисляем 2'комплементное значение (-14= 10001+1 = 10010).

Таким образом, окончательный ответ - оба значения (+ve and -ve) сохраняются только в форме 2'complement.