Как перевести число в биты
На аппаратном уровне вся информация в компьютере представляет последовательность электрических сигналов. Например, в какой-то определенной ячейке памяти может быть иметься сильное напряжение, или оно может быть очень слабым. Для описания состояния сигнала информатике используется термина бит . По сути бит является наименьшей единицей информации в компьютере. Бит может иметь значение 1 (есть сигнал, что обычно соответствует напряжению от 2 до 5 V) или 0 (сигнал отсутствует или слабый — обычно от 0 до 2 V).
8 битов составляют байт . Фактически байт — это наименьшая единица информации, которую можно прочитать или записать в память большинством современных процессоров.
Один бит может принимать два значения: 0 и 1. Два бита вместе могут принимать четыре значения: 00, 01, 10 и 11. Три бита могут принимать восемь значений: 000, 001, 010, 011, 100, 101, 110 и 111. Обобщая, группа из n битов может принимать 2 n значений. Таким образом, группа из 8 бит или 1 байт может представлять 2 8 , то есть 256 уникальных значений. Таким образом, вся информация в компьютере фактически представляет последовательность бит.
Двоичная система
Поскольку бит может иметь только два значения — 1 и 0, то для записи битов применяют двоичную систему исчисления. Вообще система исчисления представляет способ записи чисел. Например, в поседневной жизни мы пользуемся десятичной системой исчисления . Это значит, что основанием этой системы является число 10, а каждый символ числа может иметь 10 вариантов значений — от 0 до 9. В десятичной системе каждое число можно представить как сумму цифер чисел, умноженных на 10 в степени, соответствующей порядковому номеру цифры в этом числе (нумерация начинается с нуля). Например, стандартное число 123 можно представить следующим образом:
12310 = 1 * 102 + 2 * 101 + 3 * 100 = 100 + 20 + 3
Или возьмем другое десятичное число — 123,45
123,4510 = 1 * 102 + 2 * 101 + 3 * 100 + 4 * 10-1 + 5 * 10-2 = 100 + 20 + 3 + 0,4 + 0,05
В двоичной системе каждый символ числа может иметь только два значения — 1 и 0, например, число 1101. Чтобы перевести число из двоичной системы в десятичную умножаем значение каждого бита (1 или 0) на число 2 в степени, равной номеру бита (нумерация битов идет от нуля):
// перевод двоичного числа 1101 в десятичную систему 1 * 23 + 1 * 22 + 0 * 21 + 1 * 20 = 1 * 8 + 1 * 4 + 0 * 2 + 1 * 1 = 8 + 4 + 0 + 1 = 13
Перевод десятичного числа в двоичную систему выглядит несколько сложнее. Стандартный алгоритм преобразования подразумевает деление числа и результатов последующих делений на 2 и помещение остатков от деления в результат. Например, переведем десятичное число 13 в двоичную систему:
// перевод десятичного числа 13 в двоичную систему 13 / 2 = 6 // остаток 1 (13 - 6 *2 = 1) 6 / 2 = 3 // остаток 0 (6 - 3 *2 = 0) 3 / 2 = 1 // остаток 1 (3 - 1 *2 = 1) 1 / 2 = 0 // остаток 1 (1 - 0 *2 = 1)
Общий алгоритм состоит в последовательном делении числа и результатов деления на 2 и получение остатков, пока не дойдем до 0. Затем выстраиваем остатки в линию в обратном порядке и таким образом формируем двоичное представление числа. Конкретно в данном случае по шагам:
- Делим число 13 на 2. Результат деления — 6, остаток от деления — 1 (так как 13 — 6 *2 = 1)
- Далее делим результат предыдущей операции деления — число 6 на 2. Результат деления — 3, остаток от деления — 0
- Делим результат предыдущей операции деления — число 3 на 2. Результат деления — 1, остаток от деления — 1
- Делим результат предыдущей операции деления — число 1 на 2. Результат деления — 0, остаток от деления — 1
- Последний результат деления равен 0, поэтому завершаем процесс и выстраиваем остатки от операций делений, начиная с последнего — 1101
Шестнадцатиричная система
Если число большое, то запись двоичных чисел может быть довольно длинной и поэтому не очень удобной. Например, число 23410 в двоичной системе равно 111010102 . И для упрощения работы с двоичными числами применяется шестнадцатеричная система.
В шестнадцатеричной системе счисления двоичные числа разделены на группы по 4 бита. При 4 битах в группе количество возможных значений равно 24 или 16. Первым 10 из этих 16 чисел присваиваются цифры 0–9, а последним 6 — буквы A-F:
Двоичное число 11101010 можно представить более компактно, разбив его на две 4-битные группы (1110 и 1010) и записав их в виде шестнадцатеричных цифр EA .
Алгоритм перевода из шестнадцатеричной системы в десятичную и обратно тот же, что и для двоичной, только вместо 2 используется число 16. Например, шестнадцатеричное число E6 можно представить следующим образом:
e6 = e * 161 + 6 * 160 = 14 * 16 + 6 = 23010 (десятичная система) = 1110 01102 (двоичная система)
А чтобы получить из 10-тичного числа 16-ричное, делим число на 16 и получаем остатки:
// перевод десятичного числа 230 в шестнадцатеричную систему 230 / 16 = 14 // остаток 6 (230 - 16 * 14 = 230 - 224) 14 / 16 = 0 // остаток 14 или E в 16-й системе // результат 0xE6
Чтобы указать, что число шестнадцатеричное, перед ним указываются символы 0X или 0x , например, 0xE6
Стоит отметить, что 4 бита, которые соответствуют одной шестнадцатеричной цифре, называется nibble или полубайт(слог, тертрада)
При работе с разными системами счисления легко запутаться. Например, какую систему в реальности представляет число 1010 ? Оно может равным образом представлять и десятичную, и двоичную, и шестнадцатеричную. И чтобы указать, что число относится к определенной системе счисления, используют различные обозначения. Так, для указания, что число является двоичным, перед число обычно ставится префикс 0b :
0b1010 - двоичное число (в десятичной системе равно 10, а в шестнадцатеричной - A)
Чтобы указать, что число является шестнадцатеричным, перед число обычно ставится префикс 0x :
0x1010 - шестнадцатеричное число (в десятичной системе равно 4112, а в двоичной - 1000000010000)
Представление отрицательных чисел
Для представления отрицательных чисел обычно применяется two’s complement ( дополнение до 2 ). С точки зрения математики чтобы получить отрицательный аналог числа надо от 0 (нуля) вычесть это число. Например, для получения -1 надо произвести операцию 0 — 1 = -1 . С точки зрения архитектуры компьютера в качестве 0 выступает число 2 N . В данном случае степень N представляет количество битов в числе.
Например, наше число состоит из 8 бит (1 байт), наподобие 0000 0001 (1 в десятичной системе). И мы хотим получить число -1. Для этого выполняем следующую операцию:
28 - 1 = 256 - 1 = 255
Но 255 — это в десятичной системе. А как это будет выглядеть в двоичной системе:
28 - 1 = 10000 0000 - 0000 0001 = 1111 1111
Таким образом, для 8 битное отрицательное число -1 в двоичной системе будет представлять 1111 1111
Аналогичная операция в шестнадцатеричной системе:
28 - 1 = 0x100 - 1 = 0xFF
Если же мы выполним обратную операцию — к 1111 1111 прибавим изначальное число 0000 0001 , то мы получим степень двойки. Поэтому подобное представление отрицательных чисел и называется дополнение до 2-х.
Простой способ получить из положительного числа отрицательного и наборот (то есть фактически умножение на -1) заключается в том, чтобы инвертировать биты — биты 0 поменять на 1, а 1 на 0, и затем прибавить 1. Например, получим число -3. Для этого сначала возьмем двоичное представление числа 3:
310 = 0000 00112
~0000 0011 = 1111 1100
1111 1100 + 1 = 1111 1101
Таким образом, число 1111 1101 является двоичным представлением числа -3, что в шестнадцатеричной системе аналогично 0xFD
Другой пример, число 1 в двоичной системе равно 0b0000001 . Чтобы получить число -1, сначала инвертируем биты:
~0000 0001 = 1111 1110
Далее прибавляем 1:
1111 1110 + 1 = 1111 1111
То есть число -1 в двоичной системе равно 1111 1111 или 0xFF (в шестнадцатеричной системе)
Подобным образом можно получить обратно число 1:
~1111 1111 = 0000 0000 0000 0000 + 1 = 0000 0001
Соответственно, в зависимости от того, какое именно это число — положительное или отрицательно, интерпретировать это число можно по разному. Например, если число 1111 1111 рассматривается как положительное, то в десятичной системе оно равно 255. Если же оно рассматривается как отрицательное, то в десятичной системе оно равно -1.
Таким образом, 8-битные числа со знаком охватывают диапазон от -128 до 127, а 8-битные числа без знака — от 0 до 255.
Инструкции
Основу программы на ассемблере составляют инструкции — некоторые действия, например, сложение двух значений, помещение в регистр значения и т.д. При выполнении программы процессор выбирает и интерпретирует каждую инструкцию. Как и все данные, каждая инструкция, каждое действие в программе представляет последовательность битов. Каждой инструкции сопоставляется определенный машинный двоичный код, который также называется кодом инструкции или кодом операции (опкод, opcode).
Код операции — это один байт, определяющий основную операцию инструкции. Например, инструкция, которая копирует в регистр RAX число 1, имеет опкод C7 в шестнадцатеричной форме или 11000111 в двоичной форме. В зависимости от инструкции, ее операндов опкод меняется. Например, инструкция, которая копирует в регистр EAX число 1, имеет опкод B8 в шестнадцатеричной форме или 10111000 в двоичной форме. К опкодам инструкций следует добавить коды/значения операндов — регистра и чисел.
Написание машинного кода вручную возможно, но излишне громоздко. На практике вместо опкодов применяются так называемые мнемоники — человекочитаемые названия инструкций. Например, инструкция, которая копирует в регистр некоторое значение, имеет мнемонику mov (от слова «move» — помещать, поместить). А чтобы скопировать в регистр RAX число 1, нам достаточно написано команду
mov rax, 1
А чтобы скопировать в регистр EAX число 1, нам достаточно написано команду
mov eax, 1
Это довольно удобнее, чем в бинарной форме вводить команды.
Программа состоит из набора подобных инструкций. Процессор запускает программы через цикл выборки-выполнения (fetch-execute cycle). Компьютер считывает по одной инструкции за раз. Для этого процессор обращается к специальному регистру — указателю команд (или регистр IP), который также называется программным счетчиком (или PC) и который хранит адрес инструкции для выполнения. По сути, компьютер выполняет бесконечный цикл следующих операций:
- Считывает инструкцию с адреса памяти, указанного указателем инструкции — регистром IP/PC
- Декодирует инструкцию (т. е. выясняет, что означает инструкция)
- Перемещает указатель инструкций (регистр IP/PC) к следующей инструкции
- Выполняет указанную инструкцию
Сколько бит занимает число
Калькулятор подсчитывает число бит, нужное для записи заданного целого числа в двоичном виде, число может быть очень большим.
Этот калькулятор можно использовать для подсчета знаков, необходимых для записи большого числа в двоичном виде (число бит). Также выдается какой объем памяти требуется для хранения этого числа в памяти компьютера (число байт). Кроме этого калькулятор определяет число разрядов для вывода числа в восьмеричном, в десятичном и шестнадцатеричном виде и выводит исходное число в этих системах счисления.
Сколько бит в большом целом
Большое целое
Рассчитать
Двоичное представление
Восьмеричных разрядов
Восьмеричное представление
Десятичных разрядов
Десятичное представление
Шестнадцатеричных разрядов
Шестнадцатеричный код
Число байт
Ссылка Сохранить Виджет
Ограничения на длину числа нет — максимум зависит только от ресурсов вашего компьютера.
К примеру, число с одной тысячей нулей можно ввести вот так: 123E1000
Калькулятор вычисляет число двоичных разрядов путем преобразования числа в двоичную строку и последующего вычисления ее длины.
На практике такой способ неэффективен. Реализация более эффективного алгоритма поиска позиции старшего значащего бита во многом зависит от представления числа в памяти компьютера и сложности выполнения тех или иных операций.
Например, математически число бит можно вычислить путем округления в большую сторону логарифма по основанию 2 от заданного числа плюс 1:
Битовое представление чисел
Так как на уровне схем почти вся логика бинарная, ровно такое представление и используется для хранения чисел в компьютерах: каждая целочисленная переменная указывает на какую-то ячейку из 8 ( char ), 16 ( short ), 32 ( int ) или 64 ( long long ) бит.
#Эндианность
Единственная неоднозначность в таком формате возникает с порядком хранения битов — также называемый эндианностью. Зависимости от архитектуры он может быть разным:
- При схеме little-endian сначала идут младшие биты. Например, число $42_$ будет храниться так: $010101$.
- При записи в формате big-endian сначала идут старшие биты. Все примеры из начала статьи даны в big-endian формате.
Хотя big-endian более естественный для понимания — на бумаге мы ровно так обычно и записываем бинарные числа — по разным причинам на большинстве современных процессоров по умолчанию используется little endian.
Иными словами, «$i$-тый бит» означает «$i$-тый младший» или «$i$-тый справа», но на бумаге мы ничего не инвертируем и записываем двоичные числа стандартным образом.
#Битовые операции
Помимо арифметических операций, с числами можно делать и битовые, которые интерпретируют их просто как последовательность битов.
#Сдвиги
Битовую запись числа можно «сдвигать» влево ( x > y ), что эквивалентно умножению или делению на степень двойки с округлением вниз.
Обычное умножение и деление — не самые быстрые операции, однако все битовые сдвиги всегда работают ровно за один такт. Как следствие, умножение и деление на какую-то фиксированную степень двойки всегда работает быстро — даже если вы не используете сдвиги явно, компилятор скорее всего будет проводить подобную оптимизацию.
#Побитовые операции
Помимо && , || и ! , существуют их побитовые версии, которые применяют соответствующую логическую операцию к целым последовательностям битов: & , | , ~ .
Также помимо них есть ещё операция исключающего «или» (XOR), которая записывается как ^ .
- $13$ & $7$ = $1101_2$ & $0111_2$ = $0101_2$ = $5$
- $17$ | $10$ = $10001_2$ | $01010_2$ = $11011_2$ = $27$
- $17$ ^ $9$ = $10001_2$ ^ $01001_2$ = $11000_2$ = $24$
Все побитовые операции тоже работают за один такт, вне зависимости от типа данных. Для больших не вмещающихся в один регистр битовых последовательностей существует битсет.
#Маски
Бинарные последовательности можно поставить в соответствие подмножествам какого-то фиксированного множества: если на $i$-той позиции стоит единица, то значит $i$-тый элемент входит множество, а иначе не входит.
Битовые операции таким образом часто используются операций над множествами, представляемыми битовыми мазками — например, в задачах на полный перебор или динамическое программирование.
#Выделить i-й бит числа
Это часто используется для проверки, принадлежит ли $i$-тый элемент множеству:
Напомним, что нумерация идет с младших бит и начинается с нуля.
#Получить число, состоящее из k единиц
#Инвертировать все биты числа
#Добавить i-й элемент в множество
#Удалить $i$-й элемент из множества
#Удалить i-й элемент из множества, если он есть
Также добавляет этот элемент, если его нет.
#Знаковые числа
Целочисленные переменные делятся на два типа — знаковые (signed) и беззнаковые (unsigned).
Если сложить две unsigned int переменные, сумма которых превосходит $2^$, произойдет переполнение: сумму нельзя будет представить точно, и поэтому вместо неё результатом будут только нижние 32 бит. Все операции с беззнаковыми числами как бы проходят по модулю какой-то степени двойки.
Знаковые же типы нужны для хранения значений, которые могут быть и отрицательными. Для этого нужно выделить один бит для хранение знака — отрицательное ли число или нет — немного пожертвовав верхней границей представимых чисел: теперь самое большое представимое число это $2^-1$, а не $2^-1$.
Инженеры, которые работают над процессорами, ещё более ленивые, чем программисты — это мотивировано не только стремлением к упрощению, но и экономией транзисторов. Поэтому когда в signed типах происходит переполнение, результат в битовом представлении считается так же, как и в случае с unsigned числами. Если мы хотим ничего не менять в плане того, как работают unsigned числа, представление отрицательных чисел должно быть таким, что число $-x$ как бы вычитается из большой степени двойки:
- Все неотрицательные числа записываются в точности как раньше.
- У всех отрицательных чисел самый большой бит будет единичным.
- Если прибавить к $2^-1$ единицу, то результатом будет $-2^$, представляемое как 10000000 (в целях изложения мы будем записывать 8 бит, хотя в int их 32).
- Зная двоичную запись положительного числа x , запись -x можно получить как ~x + 1 .
- -1 записывается как ~1 + 1 = 11111110 + 00000001 = 11111111 .
- -42 записывается как ~42 + 1 = 11010101 + 00000001 = 11010110 .
- После -1 = 11111111 идет 0 = -1 + 1 = 11111111 + 00000001 = 00000000 .
Упражнение. Каких чисел больше: положительных или отрицательных?
Осторожно. В стандарте C/C++ прописано, что переполнение знаковых переменных приводит к undefined behavior, поэтому полагаться на описанную логику переполнения нельзя, хотя равно это скорее всего и произойдет.
#128-битные числа
Общих регистров размера больше 64 в процессорах нет, однако умножение и несколько смежных инструкций могут использовать два последовательных регистра как один большой. Это позволяет быстро перемножать два 64-битных числа и получать 128-битный результат, разделенный на нижние биты и верхние.
Это весьма специфичная операция, и поэтому в языках программирования нет полноценной поддержки 128-битных переменных. В C++ однако есть «костыль» — тип __int128_t — который фактически просто оборачивает пару из двух 64-битных регистров и поддерживает арифметические операции с ними.
Базовые арифметические операции с ним чуть медленнее, его нельзя напрямую печатать, и деление и прочие сложные операции будут вызывать отдельную библиотеку и поэтому работать очень долго, однако в некоторых ситуациях он оказывается очень полезен.
Как конвертировать число в биты
В результате получаю 1 = 110001,3 = 110011 и т.д. Откуда появляются 2 единицы в начале и как от них избавится?
Отслеживать
задан 5 мая 2019 в 10:11
65 12 12 бронзовых знаков
Строк или чисел, вижу строки, а читаю про числа. Странноватенько. Если строки то str.Select(i => Convert.ToString(i, 2)) если реальные числа, то: (byte)(num >> 8) или BitConverter.GetBytes(num)
5 мая 2019 в 10:18
@And Если я использую (byte)(num >> 8) то в ответе получаю нули вместо значений,а если BitConverter.GetBytes(num) то System.Byte[] . Пожалуйста,можете привести пример?
5 мая 2019 в 10:44
Что-что нужно сделать?? Convert.ToString(textBox1.Text); ясности не добавляет. 110001b — это ASCII-код символа «1»