Что представляет собой "-1" в диапазоне значений для unsigned int и sign int? - программирование
Подтвердить что ты не робот

Что представляет собой "-1" в диапазоне значений для unsigned int и sign int?

Я изучаю C и имею тупой вопрос относительно "-1" в диапазоне значений для unsigned int и sign int. Я не могу найти объяснение этому нигде.

Параграф ниже объясняет диапазон данных. Однако это не объясняет "-1". Что означает "-1"? Это -1, потому что пропускает 0, а 0 не имеет значения?

В 32-разрядных целых числах целое число без знака имеет диапазон от 0 до 2 ^ 32 -1 = от 0 до 4 294 967 295 или около 4 миллиардов. Подписанная версия переходит от -2 ^ 31 -1 к 2 ^ 31, что составляет от –2 147 483 648 до 2 147 483 647 или около -2 миллиардов до +2 миллиардов. Диапазон такой же, но он сдвинут на числовой линии.

4b9b3361

Ответ 1

n битов могут содержать 2 n разных значения. (Первый бит может иметь два значения * второй бит может иметь два значения * третий бит может иметь два значения *...)

Например, 3 бита могут содержать 2 3 = 8 различных значений.

000
001
010
011
100
101
110
111

Если каждая битовая комбинация представляет целое число, то n-битное целое число может представлять 2 n разных целых числа. Например,

  • Он может представлять целые числа от 0 до 2 n -1 включительно
    (поскольку (2 n -1) - (0) + 1 = 2 n различных значений).

    Например,

    000   0
    001   1
    010   2
    011   3
    100   4
    101   5
    110   6
    111   7
    
  • Он может представлять целые числа от -2 n-1 до 2 n-1 -1 включительно
    (потому что (2 n-1 -1) - (-2 n-1) + 1 = 2 n разные значения).

    Например,

    100  -4
    101  -3
    110  -2
    111  -1
    000   0
    001   1
    010   2
    011   3
    

Этим значениям можно присвоить любое значение, но ранее указанные диапазоны понятны для двух машин -complement для целых чисел без знака и целых чисел со знаком соответственно. [1]


  1. На '-complement машине есть два способа записи нуля (0000... 0000 2 и 1000... 0000 2), поэтому диапазон составляет только -2 n-1 -1 до 2 n-1 -1. Я думаю, что все современные машины - это машины двойки -complement.

Ответ 2

Рассмотрим значения, которых можно достичь с помощью 2 битов:

00 : 0
01 : 1
10 : 2
11 : 3

Всего их 4, 2 в степени 2.
Но самое большое значение не 4, а 3.
Наибольшее значение равно 2 степени 2 минус 1. Т.е. в вашем представлении

2 ^ 2 -1
или 2 2 -1

Добавьте немного, и вы получите удвоенное число, добавив

100 : 4
101 : 5
110 : 6
111 : 7

Всего 8, но наибольшее число 7.

Таким образом, "-1" заключается в том, что для 0 всегда используется первое из 2 значений n,
2-е используется для 1, 3-е используется для 2.
В конце (2 n) -й недоступен для 2 n, он уже используется для 2 n -1.

Ответ 3

Добавляя к @Yunnosch отличное объяснение чисел без знака, почти все современные компьютеры используют "два дополнения" для представления двоичных чисел со знаком. В двух дополнениях старший значащий бит используется как "знаковый бит", а биты являются дополнением к абсолютному значению числа +1. Так, для примера с 3 битами, в то время как диапазон значений без знака равен от 0 до 7, диапазон для подписанных значений от -4 до 3:

100 : -4
101 : -3
110 : -2
111 : -1
000 :  0
001 :  1
010 :  2
011 :  3

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

Ответ 4

Для целого типа без знака значение -1 равно вне диапазона и не может быть представлено в переменной этого типа. Если вы попытаетесь присвоить -1 unsigned int, преобразование произойдет в соответствии с правилами стандарта C.

Преобразование значения со знаком в целочисленный тип без знака указано в разделе 6.3.1.3p2 стандарта C:

В противном случае, если новый тип без знака, значение конвертируется путем многократного сложения или вычитания более максимальное значение, которое может быть представлено в новом типе пока значение не окажется в диапазоне нового типа. 60

...

60) Правила описывают арифметику математического значения, а не значения данного типа выражения

Предполагая, как в вашем примере, что unsigned int имеет диапазон значений от 0 до 4 294 967 295, значение -1 преобразуется путем сложения -1 + 4 294 967 296 = 4 294 967 295. Обратите внимание, что это преобразование происходит независимо от того, как отрицательные числа представлены в данной системе. То же самое для двух комплиментов: комплимента или знака и величины.

Обратите внимание, что это означает, что представление преобразованного значения не обязательно должно совпадать с представлением -1.

Используя 4-битный тип в качестве примера, преобразование значения -1 в тип без знака приводит к значению 15. Представление этих чисел выглядит следующим образом:

                sign-and magnitude    ones' complement   two complement
  -1   (signed)               1001                1110               1111
  15 (unsigned)               1111                1111               1111

Хотя в случае двух дополнений результат преобразования сохраняет одно и то же представление, он изменяется в двух других случаях. Для одного дополнения представление -1 такое же, как для 14, а для знака и величины представление -1 такое же, как для 9.

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

Ответ 5

Где вы нашли этот неверный абзац? Похоже, что это около 2 дополнений, но -1 находится не в том месте.

Для реализаций C, использующих одно целое число со знаком в виде дополнения или знака/величины, диапазон симметричен относительно нуля (с 2-битными комбинациями, которые оба представляют 0, поэтому положительный диапазон и отрицательный диапазон имеют одинаковый размер).

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


В 2 дополнении (почти универсальном в наши дни) диапазон представимых значений с использованием n битов [- 2 n-1, 2 n-1 - 1]. Один битовый шаблон (все биты ноль) представляет значение ноль. Каждый бит имеет значение места 2^i, за исключением последнего, который имеет значение места -2^(n-1).

Битовая последовательность со всеми установленными битами представляет -1, потому что sum(2^i, i=0..n-1) на единицу меньше, чем 2^n.

Если установлен только знаковый бит, мы получаем наиболее отрицательное число: -INT_MIN переполнено со знаком (неопределенное поведение), поскольку оно не может быть представлено как int; это требует более широкого целого числа. Или с упаковкой, -INT_MIN = INT_MIN. Это "аномалия 2 дополнения". https://en.wikipedia.org/wiki/Two%27s_complement#Most_negative_number

Вы можете избежать расширения, если выполняете операцию с абсолютным значением: например,
unsigned abs = i >= 0 ? i : -(unsigned)i;

(Преобразование отрицательного значения в unsigned в C имеет четко определенное поведение уменьшения по модулю до тех пор, пока оно не окажется в представимом диапазоне. В C это не зависит от кодирования со знаком-целым числом; важно значение. Так что (uint8_t)-1 всегда 255. Для дополнения 2 он просто копирует битовый шаблон. Для знака/величины или одного дополнения реализация C должна была бы выполнить некоторую математику для преобразования из подписанного в подписанное. Обратите внимание, что я сделал это до отрицания, что означает 0 - i с обычной неподписанной упаковкой.)