Сколько уникальных значений может принимать 1 байт?

11 ответов на вопрос “Сколько уникальных значений может принимать 1 байт?”

  1. Dairg Ответить

    1 байт не может вместить 256 символов, одним байтом можно закодировать любой один из 256-ти символов, потому что именно столько уникальных комбинаций может принять последовательность из 8-ми двоичных бит. Один двоичный бит – это наименьшая единица количества информации, он может принять лишь два значения 0 и 1. Последовательность двух бит может принят уже 4 значения: 00, 01, 10 и 11, а из трех бит 8 значений, 000, 001 и так далее. Добавление каждого бита увеличивает количество возможных значений, которая может принять битовая последовательность в два раза, соответственно последовательность из 8 бит сможет принять 256 различных значений. Поэтому и используют степени двойки, так как 2 в степени N равно тому, сколько значений может принять последовательность из N двоичных бит.
    Далее, существуют кодовые таблицы (ASCII, Win-1251 и т.п.), в которых каждым символам, таким как: большие и маленькие буквы английского и национального алфавитов, цифры, знаки препинания и спецсимволы, соответствует определенное значение байта, например для символа Q – это 81, соответственно 01010001. И всего в таблице и есть 256 символов, но при этом одним байтом можно “написать” один символ, а что-бы его потом прочитать, необходимо знать какая кодовая таблица, так называемая “кодировка”, использовалась.

  2. Arashizil Ответить

    Исторически сложилось так, что техническое обеспечение компьютера представляет собой электрические или электронные цепи, поэтому информация, с которой имеет дело компьютер, представляется в виде наборов электрических сигналов. При этом единицей информации принято считать состояние или из двух возможных состояний простейшего элемента.
    Поясним сказанное более подробно. Наличие электрического сигнала можно принять за единицу, а отсутствие этого сигнала – за нуль. Точно так же единицей или нулем можно считать наличие высокого или низкого напряжения в какой-то точке электрической цепи. Поскольку наличие или отсутствие сигнала соответствует двум возможным состояниям информационного элемента, то при регистрации информации с помощью только единиц или нулей удобнее пользоваться не десятичной, а двоичной системой счисления. По этой причине компьютер работает с двоичными числами.
    Двоичная структура информации является настолько общей, что если даже представить себе какой-нибудь компьютер далекой внеземной цивилизации, то и он, наверное, был бы построен по двоичному принципу. Кроме двоичной системы, сравнительно эффективной для ЭВМ является также троичная система счисления.
    Двоичная цифра в переводе на английский язык звучит как . Используя из этого термина несколько букв в качестве аббревиатуры, получим слово . Таким образом, битом называется, двоичный информационный элемент, способный принимать значение или .
    Вся информация в компьютере представляется в виде наборов таких битов. Если один бит может устанавливаться в одно из двух возможных состояний, обозначенных как или , то группа из двух расположенных рядом битов может принимать уже одно из четырех возможных состояний: 00, 01, 10 и 11.
    Клавиатура пишущей машинки содержит 80 различных печатных знаков. Чтобы охватить такую группу символов, требуется 7 бит или, как их иногда называют, 7 двоичных разрядов, с помощью которых можно реализовать 128 различных комбинаций.
    Как правило, биты группируются в цепочки по 4 двоичных разряда каждая, называемые тетрадами. Объединение двух таких тетрад дает возможность составить 16×16 = 256 различных двоичных сочетаний.
    Кроме ТОГО, объединив биты в группу из 4 элементов, с помощью такой группы можно реализовать 16 разных двоичных комбинаций, связав их с цифрами 16-ричной системы счисления. В этих комбинациях двоичное число 0000 будет соответствовать 16-ричному пулю, 0001-единице, 0010 – двойке и так далее до 9. Начиная с 10, число уже нельзя представить с помощью одной цифры, и поэтому в 16-ричной системе в качестве цифр, соответствующих 10 и выше, до 15, вводятся буквы латинского алфавита от А до F. Таким образом, числу 1010 соответствует А, числу 1011- В и так до числа 1111, обозначаемого с помощью F. В результате посредством цифр от 0 до F (заметим еще раз, что латинские буквы А – F обозначают здесь последние 6 цифр в 16-ричной системе счисления) можно выразить группу символов, состоящую из 4 бит или 4 двоичных разрядов. Такое представление намного удобнее длинных цепочек из единиц и нулей. Используя два разряда такого 16-ричного числа, можно, как уже говорилось выше, образовать 256 различных сочетаний, с помощью которых можно поочередно закодировать все символы клавиатуры. Если применить все 256 комбинаций, то их окажется достаточно, чтобы закодировать все прописные и строчные буквы латинского алфавита, знаки препинания (скобки, запятые и др.) и даже знаки японского алфавита – каны. Разумеется, для кодирования всех иероглифов, число которых достигает нескольких тысяч; 256 чисел не хватит.
    Что такое байт
    Группы из 8 бит или, что примерно то же самое, группы из двух 16-ричных разрядов, представляющие символьную информацию в ЭВМ, получили в вычислительной технике особое название: такие группы стали называться (byte).
    Итак, 1 байт содержит в себе 8 бит. Правда, в некоторых компьютерах 1 байт эквивалентен 6 бит. Но всегда единица информации, наз

  3. Goltilkis Ответить

    Перевод статьи Халида Азада — Understanding Big and Little Endian Byte Order
    Проблемы с порядком байтов очень расстраивают, и я хочу избавить Вас от горя, которое довелось испытать мне. Вот ключевые тезы:
    Проблема: Компьютеры, как и люди, говорят на разных языках. Одни записывают данные “слева направо” другие “справа налево”. При этом каждое устройство отлично считывает собственные данные — проблемы начинаются, когда один компьютер сохраняет данные, а другой пытается эти данные считать.
    Решение: Принять некий общий формат (например, весь сетевой трафик передается в едином формате). Или всегда добавлять заголовок, описывающий формат хранения данных. Если считанный заголовок имеет обратный порядок, значит данные сохранены в другом формате и должны быть переконвертированы.

    Числа и данные

    Наиболее важная концепция заключается в понимании разницы между числами и данными, которые эти числа представляют. Число — это абстрактное понятия, как исчислитель чего-то. У Вас есть десять пальцев. Понятие “десять” не меняется, в зависимости от использованного представления: десять, 10, diez (испанский), ju (японский), 1010 (бинарное представление), Х (римские числа)… Все эти представления указывают на понятие “десяти”.
    Сравним это с данными. Данные — это физическое понятие, просто последовательность битов и байтов, хранящихся на компьютере. Данные не имеют неотъемлемого значения и должны быть интерпретированы тем, кто их считывает.
    Данные — это как человеческое письмо, просто набор отметок на бумаге. Этим отметкам не присуще какое-либо значение. Если мы видим линию и круг (например, |O), то можно интерпретировать это как “десять”. Но это лишь предположение, что считанные символы представляют число. Это могут быть буквы “IO” — название спутника Юпитера. Или, возможно, имя греческой богини. Или аббревиатура для ввода/вывода. Или чьи-то инициалы. Или число 2 в бинарном представлении (“10”). Этот список предположений можно продолжить. Дело в том, что один фрагмент данных (|O) может быть интерпретировано по разному, и смысл остается не ясен, пока кто-то не уточнит намерения автора.
    Компьютеры сталкиваются с такой же проблемой. Они хранят данные, а не абстрактные понятия, используя при этом 1 и 0. Позднее они считывают эти 1 и 0 и пытаются воссоздать абстрактные понятия из набора данных. В зависимости от сделанных допущений, эти 1 и 0 могут иметь абсолютно разное значение.
    Почему так происходит? Ну, вообще-то нет такого правила, что компьютеры должны использовать один и тот же язык, так же, как нет такого правила и для людей. Каждый компьютер одного типа имеет внутреннюю совместимость (он может считывать свои собственные данные), но нет никакой гарантии, как именно интерпретирует эти данные компьютер другого типа.
    Основные концепции:
    Данные (биты и байты или отметки на бумаге) сами по себе не имеют смысла. Они должны быть интерпретированы в какое-то абстрактное понятие, например, число.
    Как и люди, компьютеры имеют различные способы хранения одного и того же абстрактного понятия (например, мы можем различными способами сказать “10”).

    Храним числа как данные

    К счастью, большинство компьютеров хранят данные всего в нескольких форматах (хотя так было не всегда). Это дает нам общую отправную точку, что делает жизнь немного проще:
    Бит имеет два состояния (включен или выключен, 1 или 0).
    Байт — это последовательность из 8 бит. Крайний левый бит в байте является старшим. То есть двоичная последовательность 00001001 является десятичным числом девять. 00001001 = (2^3 + 2^0 = 8 + 1 = 9).
    Биты нумеруются справа налево. Бит 0 является крайним правым и он наименьший. Бит 7 является крайним левым и он наибольший.
    Мы можем использовать эти соглашения в качестве строительного блока для обмена данными. Если мы сохраняем и читаем данные по одному байту за раз, то этот подход будет работать на любом компьютере. Концепция байта одинаковая на всех машинах, понятие “байт 0” одинакова на всех машинах. Компьютеры также отлично понимают порядок, в котором Вы посылаете им байты — они понимают какой байт был прислан первым, вторым, третьим и т. д. “Байт 35” будет одним и тем же на всех машинах.
    Так в чем же проблема — компьютеры отлично ладят с одиночными байтами, правда? Ну, все превосходно для однобайтных данных, таких как ASCII-символы. Однако, много данных используют для хранения несколько байтов, например, целые числа или числа с плавающей точкой. И нет никакого соглашения о том, в каком порядке должны хранится эти последовательности.

    Пример с байтом

    Рассмотрим последовательность из 4 байт. Назовем их W X Y и Z. Я избегаю наименований A B C D, потому что это шестнадцатеричные числа, что может немного запутывать. Итак, каждый байт имеет значение и состоит из 8 бит.
    Имя байта W X Y Z
    Позиция 0 1 2 3
    Значение (hex) 0x12 0x34 0x56 0x78
    Например, W — это один байт со значением 0х12 в шестнадцатеричном виде или 00010010 в бинарном. Если W будет интерпретироваться как число, то это будет “18” в десятеричной системе (между прочим, ничто не указывает на то, что мы должны интерпретировать этот байт как число — это может быть ASCII-символ или что-то совсем иное). Вы все еще со мной? Мы имеем 4 байта, W X Y и Z, каждый с различным значением.

    Понимаем указатели

    Указатели являются ключевой частью программирования, особенно в языке С. Указатель представляет собой число, являющееся адресом в памяти. И это зависит только от нас (программистов), как интерпретировать данные по этому адресу.
    В языке С, когда вы кастите (приводите) указатель к конкретному типу (такому как char * или int *), это говорит компьютеру, как именно интерпретировать данные по этому адресу. Например, давайте объявим:
    void *p = 0; // p указатель на неизвестный тип данных
    // p нулевой указатель – не разыменовывать
    char *c; // c указатель на один байт
    Обратите внимание, что мы не можем получить из р данные, потому что мы не знаем их тип. р может указывать на цифру, букву, начало строки, Ваш гороскоп или изображение — мы просто не знаем, сколько байт нам нужно считать и как их интерпретировать.
    Теперь предположим, что мы напишем:
    c = (char *)p;
    Этот оператор говорит компьютеру, что р указывает на то же место, и данные по этому адресу нужно интерпретировать как один символ (1 байт). В этом случае, с будет указывать на память по адресу 0, или на байт W. Если мы выведем с, то получим значение, хранящееся в W, которое равно шестнадцатеричному 0x12 (помните, что W — это полный байт). Этот пример не зависит от типа компьютера — опять же, все компьютеры одинаково хорошо понимают, что же такое один байт (в прошлом это было не всегда так).
    Этот пример полезен, он одинаково работает на все компьютерах — если у нас есть указатель на байт (char *, один байт), мы можем проходить по памяти, считывая по одному байту за раз. Мы можем обратиться к любому месту в памяти, и порядок хранения байт не будет иметь никакого значения — любой компьютер вернет нам одинаковую информацию.

    Так в чем же проблема?

    Проблемы начинаются, когда компьютер пытается считать несколько байт. Многие типы данных состоят больше чем из одного байта, например, длинные целые (long integers) или числа с плавающей точкой. Байт имеет только 256 значений и может хранить числа от 0 до 255.
    Теперь начинаются проблемы — если Вы читаете многобайтные данные, то где находится старший байт?
    Машины с порядком хранения от старшего к младшему (прямой порядок) хранят старший байт первым. Если посмотреть на набор байтов, то первый байт (младший адрес) считается старшим.
    Машины с порядком хранения от младшего к старшему (обратный порядок) хранят младший байт первым. Если посмотреть на набор байт, то первый байт будет наименьшим.
    Такое именование имеет смысл, правда? Тип хранения от старшего к младшему подразумевает, что запись начинается со старшего и заканчивается младшим (Между прочим, английский вариант названий от старшего к младшего (Big-endian) и от младшего к старшему (Little-endian) взяты из книги “Путешествия Гулливера”, где лилипуты спорили о том, следует ли разбивать яйцо на маленьком конце (little-end) или на большом (big-end)). Иногда дебаты компьютеров такие же осмысленные 🙂
    Повторюсь, порядок следования байтов не имеет значения пока Вы работаете с одним байтом. Если у Вас есть один байт, то это просто данные, которые Вы считываете и есть только один вариант их интерпретации (опять таки, потому что между компьютерами согласовано понятие одного байта).
    Теперь предположим, что у нас есть 4 байта (WXYZ), которые хранятся одинаково на машинах с обоими типами порядка записи байтов. То есть, ячейка памяти 0 соответствует W, ячейка 1 соответствует X и т. д.
    Мы можем создать такое соглашение, помня, что понятие “байт” является машинно-независимым. Мы можем обойти память по одному байту за раз и установить необходимые значения. Это будет работать на любой машине.
    c = 0; // указывает на позицию 0 (не будет работать на реальной машине!)
    *c = 0x12; // устанавливаем значение W
    c = 1; // указывает на позицию 1
    *c = 0x34; // устанавливаем значение X
    … // то же повторяем для Y и Z
    Такой код будет работать на любой машине и успешно установит значение байт W, X, Y и Z расположенных на соответствующих позициях 0, 1, 2 и 3.

    Интерпретация данных

    Теперь давайте рассмотрим пример с многобайтными данными (наконец-то!). Короткая сводка: “short int” это 2-х байтовое число (16 бит), которое может иметь значение от 0 до 65535 (если оно беззнаковое). Давайте используем его в примере.
    short *s; // указатель на short int (2 байта)
    s = 0; // указатель на позицию 0; *s это значение
    Итак, s это указатель на short int, и сейчас он указывает на позицию 0 (в которой хранится W). Что произойдет, когда мы считаем значение по указателю s?
    Машина с прямым порядком хранения: Я думаю, short int состоит из двух байт, а значит я считаю их. Позиция s это адрес 0 (W или 0х12), а позиция s + 1 это адрес 1 (X или 0х34). Поскольку первый байт является старшим, то число должно быть следующим 256 * байт 0 + байт 1 или 256 * W + X, или же 0х1234. Я умножаю первый байт на 256 (2^8) потому что его нужно сдвинуть на 8 бит.
    Машина с обратным порядком хранения: Я не знаю что курит мистер “От старшего к младшему”. Я соглашусь, что short int состоит из 2 байт и я считаю их точно также: позиция s со значение 0х12 и позиция s + 1 со значением 0х34. Но в моем мире первым является младший байт! И число должно быть байт 0 + 256 * байт 1 или 256 * X + W, или 0х3412.
    Обратите внимание, что обе машины начинали с позиции s и читали память последовательно. Не никакой путаницы в том, что значит позиция 0 и позиция 1. Как и нет никакой путаницы в том, что являет собой тип short int.
    Теперь Вы видите проблему? Машина с порядком хранения от старшего к младшему считает, что s = 0x1234, в то время как машина с порядком хранения от младшего к старшему думает, что s = 0x3412. Абсолютно одинаковые данные дают в результате два совершенно разных числа.

    И еще один пример

    Давайте для “веселья” рассмотрим еще один пример с 4 байтовым целым:
    int *i; // указатель на int (4 байты 32-битовой машине)
    i = 0; // указывает на позицию 0, а *i значение по этому адресу
    И опять мы задаемся вопросом: какое значение хранится по адресу i?
    Машина с прямым порядком хранения: тип int состоит из 4 байт и первый байт является старшим. Считываю 4 байта (WXYZ) из которых старший W. Полученное число: 0х12345678.
    Машина с обратным порядком хранения: несомненно, int состоит из 4 байт, но старшим является последний. Так же считываю 4 байта (WXYZ), но W будет расположен в конце — так как он является младшим. Полученное число: 0х78563412.
    Одинаковые данные, но разный результат — это не очень приятная вещь.

    Проблема NUXI

    Проблему с порядком байт иногда называют проблемой NUXI: слово UNIX, сохраненное на машинах с порядком хранения от старшего к младшему, будет отображаться как NUXI на машинах с порядком от младшего к старшему.
    Допустим, что мы собираемся сохранить 4 байта (U, N, I, и X), как два short int: UN и IX. Каждая буква занимает целый байт, как в случае с WXYZ. Для сохранения двух значений типа short int напишем следующий код:
    short *s; // указатель для установки значения переменной типа short
    s = 0; // указатель на позицию 0
    *s = UN; // устанавливаем первое значение: U * 256 + N (вымышленный код)
    s = 2; // указатель на следующую позицию
    *s = IX; // устанавливаем второе значение: I * 256 + X
    Этот код не является специфичным для какой-то машины. Если мы сохраним значение “UN” на любой машине и считаем его обратно, то обратно получим тоже “UN”. Вопрос порядка следования байт не будет нас волновать, если мы сохраняем значение на одной машине, то должны получить это же значение при считывании.
    Однако, если пройтись по памяти по одному байту за раз (используя трюк с char *), то порядок байт может различаться. На машине с прямым порядком хранения мы увидим:
    Byte: U N I X
    Location: 0 1 2 3
    Что имеет смысл. “U” является старшим байтом в “UN” и соответственно хранится первым. Такая же ситуация для “IX”, где “I” — это старший байт и хранится он первым.
    На машине с обратным порядком хранения мы скорее всего увидим:
    Byte: N U X I
    Location: 0 1 2 3
    Но и это тоже имеет смысл. “N” является младшим байтом в “UN” и значит хранится он первым. Опять же, хотя байты хранятся в “обратном порядке” в памяти, машины с порядком хранения от младшего к старшему знают что это обратный порядок байт, и интерпретирует их правильно при чтении. Также, обратите внимание, что мы можем определять шестнадцатеричные числа, такие как 0x1234, на любой машине. Машина с обратным порядком хранения байтов знает, что Вы имеете в виду, когда пишите 0x1234 и не заставит Вас менять значения местами (когда шестнадцатеричное число отправляется на запись, машина понимает что к чему и меняет байты в памяти местами, скрывая это от глаз. Вот такой трюк.).
    Рассмотренный нами сценарий называется проблемой “NUXI”, потому что последовательность “UNIX” интерпретируется как “NUXI” на машинах с различным порядком хранения байтов. Опять же, эта проблема возникает только при обмене данными — каждая машина имеет внутреннюю совместимость.

    Обмен данными между машинами с различным порядком хранения байтов

    Сейчас компьютеры соединены — прошли те времена, когда машинам приходилось беспокоиться только о чтении своих собственных данных. Машинам с различным порядком хранения байтов нужно как-то обмениваться данными и понимать друг друга. Как же они это делают?
    Решение 1: Использовать общий формат
    Самый простой подход состоит в согласовании с общим форматом для передачи данных по сети. Стандартным сетевым является порядок от старшего к младшему, но некоторые люди могут расстроиться, что не победил порядок от младшего к старшему, поэтому просто назовем его “сетевой порядок”.
    Для конвертирования данных в соответствии с сетевым порядком хранения байтов, машины вызывают функцию hton() (host-to-network). На машинах с прямым порядком хранения эта функция не делает ничего, но мы не будем говорить здесь об этом (это может разозлить машины с обратным порядком хранения 🙂 ).
    Но важно использовать функцию hton() перед отсылкой данных даже если Вы работаете на машине с порядком хранения от старшего к младшему. Ваша программа может стать весьма популярной и будет скомпилирована на различных машинах, а Вы ведь стремитесь к переносимости своего кода (разве не так?).
    Точно также существует функция ntoh() (network-to-host), которая используется для чтения данных из сети. Вы должны использовать ее, чтобы быть уверенными, что правильно интерпретируете сетевые данные в формат хоста. Вы должны знать тип данных, которые принимаете, чтобы расшифровать их правильно. Функции преобразования имеют следующий вид:
    htons() – “Host to Network Short”
    htonl() – “Host to Network Long”
    ntohs() – “Network to Host Short”
    ntohl() – “Network to Host Long”
    Помните, что один байт — это один байт и порядок не имеет значения.
    Эти функции имеют критическое значение при выполнении низкоуровневых сетевых операций, таких как проверка контрольной суммы IP-пакетов. Если Вы не понимаете сути проблемы с порядком хранения байтов, то Ваша жизнь будет наполнена болью — поверьте мне на слово. Используйте функции преобразования и знайте, зачем они нужны.
    Решение 2: Использования маркера последовательности байтов (Byte Order Mark — BOM)
    Этот подход подразумевает использование некого магического числа, например 0xFEFF, перед каждым куском данных. Если Вы считали магическое число и его значение 0xFEFF, значит данные в том же формате, что и у Вашей машины и все хорошо. Если Вы считали магическое число и его значение 0xFFFE, это значит, что данные были записаны в формате, отличающемся от формата вашей машины и Вы должны будете преобразовать их.
    Нужно отметить несколько пунктов. Во-первых, число не совсем магическое, как известно программисты часто используют этот термин для описания произвольно выбранных чисел (BOM может быть любой последовательностью различных байтов). Такая пометка называется маркером последовательности байтов потому что показывает в каком порядке данные были сохранены.
    Во-вторых, BOM добавляет накладные расходы для всех передаваемых данных. Даже в случае передачи 2 байт информации Вы должны добавлять к ним 2 байта маркера BOM. Пугающе, не так ли?
    Unicode использует BOM, когда сохраняет многобайтные данные (некоторые кодировки Unicode могут иметь по 2, 3 и даже 4 байта на символ). XML позволяет избежать этой путаницы, сохраняя данные сразу в UTF-8 по умолчанию, который сохраняет информацию Unicode по одному байту за раз. Почему это так круто?
    Повторяю в 56-й раз — потому что проблема порядка хранения не имеет значения для единичных байт.
    Опять же, в случае использования BOM может возникнуть другие проблемы. Что, если Вы забудете добавить BOM? Будете предполагать, что данные были отправлены в том же формате, что и Ваши? Прочитаете данные и, увидев что они “перевернуты” (что бы это не значило), попытаетесь преобразовать их? Что, если правильные данные случайно будут содержать неправильный BOM? Эти ситуации не очень приятные.

    Почему вообще существует эта проблема? Нельзя ли просто договориться?

    Ох, какой же это философский вопрос. Каждый порядок хранения байтов имеет свои преимущества. Машины с порядком следования от младшего к старшему позволяют читать младший байт первым, не считывая при этом остальные. Таким образом можно легко проверить является число нечетным или четным (последний бит 0), что очень здорово, если Вам необходима такая проверка. Машины с порядком от старшего к младшему хранят данные в памяти в привычном для человека виде (слева направо), что упрощает низкоуровневую отладку.
    Так почему же все просто не договорятся об использовании одной из систем? Почему одни компьютеры пытаются быть отличными от других? Позвольте мне ответить вопросом на вопрос: почему не все люди говорят на одном языке? Почему в некоторых языках письменность слева направо, а у других справа налево?
    Иногда системы развиваются независимо, а в последствии нуждаются во взаимодействии.

    Эпилог: Мысли на прощание

    Вопросы с порядком хранения байтов являются примером общей проблемы кодирования — данные должны представлять собой абстрактные понятия, и позднее это понятие должно быть создано из данных. Эта тема заслуживает отдельной статьи (или серии статей), но Вы должны иметь лучшее понимание проблемы, связанной с порядком хранения байтов.

  4. Kigar Ответить

    Минимальная единица измерения объема памяти в двоичных компьютерных системах называется БИТ (BIT).
    Бит это двоичное число, которое, как правило принимает либо 0 либо 1. Если говорить о конечном проявлении в физической форме в компьютере, то как правило это состояния “свободно”, “занято” или “нет сигнала” и “есть сигнал”.
    Вот именно от сюда проявляется важность двойки и ее степенней.
    Так как бит это очень уж маленькая единица измерения даже для переменных, не говоря уже о подсчете информации на энергонезависимых источниках памяти (жесткие диски, флешки).
    Ввели дополнительную единицу измерения называемую БАЙТ (BYTE).
    В современных компьютерных системах 1 байт равен 8 битам.
    Ранее существовали байты с большей размерностью битов.
    Байт обычно является минимальным размером в адресации оперативной памяти, то есть компьютер орудует такими блоками из восьми бит. Путем добавления приставок СИ к байту мы и получаем привычные килобайты, мегабайты и так далее.
    Любые переменные используемые в ваших программах занимают сколько то места в оперативной памяти. Место это измеряется уже в байтах.
    Посмотрим сколько значений может хранить один байт, для этого возведем 2^8 получаем 256 уникальных значений может хранить один байт.
    Почему возводим 2 в степень 8. Потому что у нас имеется восемь элементов, которые могут хранить одно из двух значений, получаем 256 возможных комбинаций от 00000000 до 11111111.
    Возьмем ключевые значения двойки, которые соответствуют последовательности байтов.
    1 байт = 2^8 = 256
    2 байта = 2^16 = 65536
    4 байта = 2^32 = 4294967296
    К примеру тип данных INTEGER часто реализуется используя 2 байта или 4 байта (а бывает и даже один), то есть теоритически может принимать 65536 или 4294967296 уникальных значений.
    На практике всегда стоит помнить, что если тип данных имеет знак, то для него отводится один бит.
    К примеру пусть у нас тип данных TinyINT (маленький INT, используется в субд MySql) будет знаковым, тогда мы получаем 2^7 = 128, так как у нас есть знак, то интервал допустимых значений будет от -128 до 127 (незабываем про 0).
    Если же наш TinyINT является беззнаковым (unsigned), то мы получаем интервал значений от 0 до 255.
    Для хранения натурального числа N нужно LOG 2 N + 1 бит.
    То есть логарифм N по основанию 2 плюс 1 бит.
    Со строками дело обстоит несколько иначе.
    Так как строка это последовательность символов, а символ может быть любой буквой, цифрой или знаком (в том числе пробелом), то каждый символ кодируется отдельно от одного до нескольких байтов.

  5. Kisar Ответить

    Решение: По формуле 25 = 32.
    Задача (обратная). Известно, что количество сотрудников фирмы не превышает 300 человек. Каждому сотруднику присваивается табельный номер. Какое количество бит необходимо для кодирования табельных номеров.
    Решение:
    1 вариант. По таблице видно, что число 300 располагается между 256 и 512. Учитывая то, что количество бит не может быть дробным, а 8 бит недостаточно для кодирования 300 значений, следовательно необходимо 9 бит.
    2 вариант. По формуле: К = 300 . Число бит должно быть целым, т.е. n = 9, т.к. с помощью 8 бит можно закодировать только 256 значений, а это не соответствует условию задачи.
    Сколько бит требуется для кодирования всех возможных в записи символов?
    Кириллица (строчные и прописные)

    66 (33 + 33)
    Латинские (строчные и прописные)

    52 (26 + 26)
    Цифры

    Знаки препинания (. , : ; ‘’ «» ! ? -)

    Математические операции (+ – * / ^)

    Спецсимволы ({} () [] # $ % & @)

    Итого:
    По формуле получаем, что необходимо 8 бит (байт), т.е. 256 различных вариантов, т.е. в запасе (256 – 156) 100 вариантов, этого вполне хватает на служебные символы и элементы псевдографики.
    Тема «Информация и управление»
    Екатеринбург
    Информация и управление
    Т.е. например, с помощью 9 бит можно закодировать 512 различных вариантов
    Задача. Какое количество информации можно закодировать с помощью 5 бит?
    Решение: По формуле 25 = 32.
    Задача (обратная). Известно, что количество сотрудников фирмы не превышает 300 человек. Каждому сотруднику присваивается табельный номер. Какое количество бит необходимо для кодирования табельных номеров.
    Решение:
    1 вариант. По таблице видно, что число 300 располагается между 256 и 512. Учитывая то, что количество бит не может быть дробным, а 8 бит недостаточно для кодирования 300 значений, следовательно необходимо 9 бит.
    2 вариант. По формуле: К = 300 . Число бит должно быть целым, т.е. n = 9, т.к. с помощью 8 бит можно закодировать только 256 значений, а это не соответствует условию задачи.
    Сколько бит требуется для кодирования всех возможных в записи символов?
    Кириллица (строчные и прописные)

    66 (33 + 33)
    Латинские (строчные и прописные)

    52 (26 + 26)
    Цифры

    Знаки препинания (. , : ; ‘’ «» ! ? -)

    Математические операции (+ – * / ^)

    Спецсимволы ({} () [] # $ % & @)

    Итого:
    По формуле получаем, что необходимо 8 бит (байт), т.е. 256 различных вариантов, т.е. в запасе (256 – 156) 100 вариантов, этого вполне хватает на служебные символы и элементы псевдографики.
    Объект, процесс, явление, система
    Весь мир вокруг нас состоит из объектов, процессов и явлений.
    Объект – часть окружающего мира, которую можно рассматривать как единое целое.
    Шкаф, ручка, дерево, тетрадь, человек.
    Каждый объект имеет имя и свойства, которые его характеризуют.
    Свойства объекта – это совокупность признаков (параметров) объекта, по которым он отличается от других объектов.
    Свойство может принимать разные значения
    Объект: Шкаф Объект: Человек
    Свойства Значения Свойства Значения
    Цвет Бук Пол М
    Материал ДСП Имя Костя
    Габариты 80х120х240 Возраст 14
    Вес 30 кг Вес 42
    Рост 160
    Цвет глаз голубой
    Цвет волос брюнет
    Темперамент холерик
    Объект существует не сам по себе, а в окружении других объектов, в определенных условиях.
    Совокупность условий, в которых объект существует, называется среда (среда обитания).
    Объект: Человек
    Условия: Воздух, вода, солнце, определенный уровень давления, общение и т.д.
    Объекты, которые производят какие-то действия над другими объектами, называют активными. Объекты, над которыми действия совершаются, называют пассивными.
    В разных случаях, один и тот же объект может быть активным и пассивным.
    Молоток – гвоздь, рука – молоток.
    Иногда объект состоит из более простых объектов.
    Автомобиль, компьютер, робот.
    В этом случае весь комплекс объектов рассматривается как система
    Система – это совокупность взаимосвязанных между собой объектов.
    3. Синтаксическая – используется для определения объема обезличенной информации (т.е. не учитывается смысл).
    Бит
    Байт = 8 бит
    1 Кб = 1024 Бит = 1010
    1 Кб = 1024 Бит = 1010
    К – кило
    М – мега
    Г – гига
    Т – тера
    1 Мб = 1024 КБит = 1020
    1 Мб = 1024 КБит = 1020
    1 Гб = 1024 МБит = 1030
    1 Гб = 1024 МБит = 1030
    1 Тб = 1024 ГБит = 1040
    1 Тб = 1024 ГБит = 1040
    Пример: 1,2 Кбт > бит
    1,2 * 1024 = 1228,8 байт = 1228,8 * 8 = 9830,4 бит.

  6. beautiful_lie Ответить

    То есть от полученного нами числа нужно взять остаток от деления на 23-1 (семь) — и мы получаем сумму наших 8-и блоков по модулю 7. Беда в том, что сумма бит может быть равна 7 или 8, в таком случае алгоритм выдаст 0 и 1 соответственно. Но давайте посмотрим: в каком случае мы можем получить ответ 8? Только когда n=255. А в каком случае можем получить 0? Только когда n=0. Поэтому если алгоритм после взятия остатка на 7 даст 0, то либо мы на входе получили n=0, либо в числе ровно 7 единичных бит. Суммируя эту рассуждение, получаем следующий код:
    u8 CountOnes3 (u8 n) {
    if (n == 0) return 0; // Единственный случай, когда ответ 0.
    if (n == 0xFF) return 8; // Единственный случай, когда ответ 8.
    n = (0x010101*n & 0x249249) % 7; // Считаем число бит по модулю 7.
    if (n == 0) return 7; // Гарантированно имеем 7 единичных битов.
    return n; // Случай, когда в числе от 1 до 6 единичных битов.
    }
    В случае когда n имеет размер 16 бит можно разбить его на две части по 8 бит. Например, так:
    u8 CountOnes3 (u16 n) {
    return CountOnes3 (u8(n&0xFF)) + CountOnes3 (u8(n>>8));
    Для случая 32-х и 64-х бит подобное разбиение не имеет смысла уже даже в теории, умножение и остаток от деления с тремя ветвлениями будут слишком дорого стоить, если выполнять их 4 или 8 раз подряд. Но я оставил для вас пустые места в нижеследующей таблице, поэтому если вы мне не верите – заполните их, пожалуйста, сами. Там скорее всего будут результаты, сравнимые с процедурой CountBits1, если у вас похожий процессор (я не говорю о том, что здесь возможны оптимизации с помощью SSE, это уже будет другой разговор).
    Режим
    u8
    u16
    u32
    u64
    x86
    12,42
    30,57


    x64
    13,88
    33,88


    Данный трюк, конечно, можно сделать и без ветвлений, но тогда нам нужно, чтобы при разбиении числа на блоки в блок вместились все числа от 0 до 8, а этого можно добиться лишь в случае 4-битовых блоков (и больше). Чтобы выполнить суммирование 4-битовых блоков, нужно подобрать множитель, который позволит правильно «растиражировать» число и взять остаток от деления на 24-1=15, чтобы сложить получившиеся блоки. Опытный алхимик (который знает математику) легко подберёт такой множитель: 0x08040201. Почему он выбран таким?

    Дело в том, что нам необходимо, чтобы все биты исходного числа заняли правильные позиции в своих 4-битовых блоках (картинка выше), а коль скоро 8 и 4 не являются взаимно простыми числами, обычное копирование 8 битов 4 раза не даст правильного расположения нужных битов. Нам придётся добавить к нашему байту один нолик, то есть тиражировать 9 битов, так как 9 взаимно просто с 4. Так мы получим число, имеющее размер 36 бит, но в котором все биты исходного байта стоят на младших позициях 4-битовых блоков. Осталось только взять побитовое «и» с числом 0x111111111 (вторая строка на картинке выше), чтобы обнулить по три старших бита в каждом блоке. Затем блоки нужно сложить.
    При таком подходе программа подсчёта единичных битов в байте будет предельно простой:
    u8 CountOnes3_x64 (u8 n) {
    return ((u64)0x08040201*n & 0x111111111) % 15;
    }
    Недостаток программы очевиден: требуется выход в 64-битовую арифметику со всеми вытекающими отсюда последствиями. Можно заметить, что в действительности данная программа задействует только 33 бита из 64-х (старшие 3 бита обнуляются), и в принципе можно сообразить, как перенести данные вычисления в 32-х битовую арифметику, но рассказы о подобных оптимизациях не входят в тему этого руководства. Давайте пока просто изучать приёмы, а оптимизировать их вам придётся самим уже под конкретную задачу.
    Ответим на вопрос о том, какого размера может быть переменная n, чтобы данный трюк правильно работал для неё. Коль скоро мы берём остаток от деления на 15, такая переменная не может иметь размер больше 14 бит, в противном случае придётся применить ветвление, как мы делали это раньше. Но для 14 бит приём работает, если добавить к 14-ти битам один нолик, чтобы все биты встали на свои позиции. Теперь я буду считать, что вы в целом усвоили суть приёма и сможете сами без труда подобрать множитель для тиражирования и маску для обнуления ненужных битов. Покажу сразу готовый результат.
    u8 CountOnes3_x64 (u14 n) { // Это не опечатка (и не должно работать)!
    return (n*0x200040008001llu & 0x111111111111111llu) % 15;
    }
    Эта программа выше показывает, как мог бы выглядеть код, будь у вас переменная размером 14 бит без знака. Этот же код будет работать с переменной в 15 бит, но при условии, что максимум лишь 14 из них равные единице, либо если случай, когда n=0x7FFF мы разберём отдельно. Это всё нужно понимать для того, чтобы написать правильный код для переменной типа u16. Идея в том, чтобы сначала «откусить» младший бит, посчитать биты в оставшемся 15-ти битовом числе, а затем обратно прибавить «откушенный» бит.
    u8 CountOnes3_x64 (u16 n) {
    u8 leastBit = n&1; // Берём младший бит.
    n >>= 1; // Оставляем только 15 бит исходного числа.
    if (n == 0) return leastBit; // Если получился 0, значит ответом будет младший бит.
    if (n == 0x7FFF) return leastBit + 15; // Единственный случай, когда ответ 15+младший бит.
    return leastBit + (n*0x200040008001llu & 0x111111111111111llu) % 15; // Ответ (максимум 14+младший бит).
    }
    Для n размером 32 бита приходится колдовать уже с более серьёзным лицом… Во-первых, ответ влезает только в 6 бит, но можно рассмотреть отдельный случай, когда n=232-1 и спокойно делать расчёты в полях размером 5 бит. Это экономит место и разрешает нам разбить 32-битовое поле числа n на 3 части по 12 бит в каждой (да, последнее поле будет не полным). Поскольку 12?5=60, мы можем тиражировать одно 12-битовое поле 5 раз, подобрав множитель, а затем сложить 5-битовые блоки, взяв остаток от деления на 31. Сделать это нужно 3 раза для каждого поля. Суммируя итог, получаем такой код:
    u8 CountOnes3_x64 ( u32 n ) {
    if (n == 0) return 0;
    if (n + 1 == 0) return 32;
    u64 res = (n&0xFFF)*0x1001001001001llu & 0x84210842108421llu;
    res += ((n&0xFFF000)>>12)*0x1001001001001llu & 0x84210842108421llu;
    res += (n>>24)*0x1001001001001llu & 0x84210842108421llu;
    res %= 0x1F;
    if (res == 0) return 31;
    return res;
    }
    Здесь точно также можно было вместо трех ветвлений взять 3 остатка от деления, но я выбрал ветвистый вариант, на моём процессоре он будет работать лучше.
    Для n размером 64 бита мне не удалось придумать подходящего заклинания, в котором было бы не так много умножений и сложений. Получалось либо 6, либо 7, а это слишком много для такой задачи. Другой вариант — выход в 128-битовую арифметику, а это уже не пойми каким «откатом» для нас обернётся, неподготовленного мага может и к стенке отшвырнуть 🙂
    Давайте лучше посмотрим на время работы.
    Режим
    u8
    u16
    u32
    u64
    x86
    39,78
    60,48
    146,78

    x64
    6,78
    12,28
    31,12

    Очевидным выводом из этой таблицы будет то, что 64-х битовая арифметика плохо воспринимается в 32-х битовом режиме исполнения, хотя в целом-то алгоритм неплох. Если вспомнить скорость алгоритма предподсчёта в режиме x64 для однобайтовой таблицы для случая u32 (24,79 с), то получим, что данный алгоритм отстаёт всего лишь на 25%, а это повод к соревнованию, воплощённому в следующем разделе.

    Замена взятия остатка на умножение и сдвиг

    Недостаток операции взятия остатка всем очевиден. Это деление, а деление – это долго. Разумеется, современные компиляторы знают алхимию и умеют заменять деление на умножение со сдвигом, а чтобы получить остаток, нужно вычесть из делимого частное, умноженное на делитель. Тем не менее, это всё равно долго! Оказывается, что в древних свитках заклинателей кода сохранился один интересный способ оптимизации предыдущего алгоритма. Мы можем суммировать k-битовые блоки не взятием остатка от деления, а ещё одним умножением на маску, с помощью которой обнуляли лишние биты в блоках. Вот как это выглядит для n размером в 1 байт.
    Для начала снова тиражируем байт трижды и удаляем по два старших бита у каждого 3-битового блока с помощью уже пройденной выше формулы 0x010101?n & 0x249249.

    Каждый трёхбитовый блок я для удобства обозначил заглавной латинской буквой. Теперь умножаем полученный результат на ту же самую маску 0x249249. Маска содержит единичный бит в каждой 3-й позиции, поэтому такое умножение эквивалентно сложению числа самого с собой 8 раз, каждый раз со сдвигом на 3 бита:

    Что мы видим? Биты с 21 по 23 и дают нам нужную сумму! При этом переполнения в каком-либо из блоков справа невозможно, так как там ни в одном блоке не будет числа, большего 7. Проблема лишь в том, что если наша сумма равна 8, мы получим 0, но это не страшно, ведь этот единственный случай можно рассмотреть отдельно.
    u8 CountOnes3_x64_m (u8 n) {
    if (n == 0xFF) return 8;
    return ((u64(0x010101*n & 0x249249) * 0x249249) >> 21) & 0x7;
    }
    По сути, мы взяли код из предыдущего раздела и заменили в нём взятие остатка от деления на 7 на умножение, сдвиг и побитовое «И» в конце. При этом вместо 3-х ветвлений осталось лишь одно.
    Чтобы составить аналогичную программу для 16 бит, нам нужно взять код из предыдущего раздела, в котором показано как это делается с помощью взятия остатка от деления на 15 и заменить данную процедуру умножением. При этом нетрудно заметить то, какие условия можно убрать из кода.
    u8 CountOnes3_x64_m (u16 n) {
    u8 leastBit = n&1; // Берём младший бит
    n >>= 1; // Оставляем только 15 бит.
    return leastBit
    + (( (n*0x200040008001llu & 0x111111111111111llu)*0x111111111111111llu
    >> 56) & 0xF); // Ответ (максимум 15 + младший бит).
    }
    Для 32-х бит мы делаем то же самое: берём код из предыдущего раздела и, порисовав немного на бумаге, соображаем, каким будет сдвиг, если заменить остаток на умножение.
    u8 CountOnes3_x64_m ( u32 n ) {
    if (n+1 == 0) return 32;
    u64 res = (n&0xFFF)*0x1001001001001llu & 0x84210842108421llu;
    res += ((n&0xFFF000)>>12)*0x1001001001001llu & 0x84210842108421llu;
    res += (n>>24)*0x1001001001001llu & 0x84210842108421llu;
    return (res*0x84210842108421llu >> 55) & 0x1F;
    }
    Для 64-х бит я тоже не смог придумать чего-то такого, чтобы не заставляло бы мой процессор выполнять роль печки.
    Режим
    u8
    u16
    u32
    u64
    x86
    12,66
    42,37
    99,90

    x64
    3,54
    4,51
    18,35

    Приятно удивили результаты для режима x64. Как и ожидалось, мы обогнали предподсчёт с однобайтовой таблицей для случая u32. Можно ли вообще обогнать предподсчёт? Хороший вопрос 🙂

    Параллельное суммирование

    Пожалуй, это самый распространённый трюк, который очень часто повторяют друг за другом не вполне опытные заклинатели, не понимая, как он точно работает.
    Начнём с 1 байта. Байт состоит из 4-х полей по 2 бита, сначала просуммируем биты в этих полях, произнеся что-то вроде:
    n = (n>>1)&0x55 + (n&0x55);
    Вот пояснительная картинка к данной операции (по-прежнему, обозначаем биты одного байта первыми латинскими буквами):

    Одно из побитовых «И» оставляет только младшие биты каждого двухбитового блока, второе оставляет старшие биты, но сдвигает их на позиции, соответствующие младшим битам. В результате суммирования получаем сумму смежных битов в каждом двухбитовом блоке (последняя строка на картинке выше).
    Теперь сложим парами числа, находящиеся в двухбитовых полях, помещая результат в 2 четырёхбитовых поля:
    n = (n>>2)&0x33 + (n&0x33);
    Нижеследующая картинка поясняет результат. Привожу её теперь без лишних слов:

    Наконец, сложим два числа в четырёхбитовых полях:
    n = (n>>4)&0x0F + (n&0x0F);

    Действуя по аналогии, можно распространить приём на любое число бит, равное степени двойки. Число строк заклинания равно двоичному логарифму от числа бит. Уловив идею, взгляните вскользь на 4 функции, записанных ниже, чтобы убедиться в правильности своего понимания.
    u8 CountOnes4 (u8 n) {
    n = ((n>>1) & 0x55) + (n & 0x55);
    n = ((n>>2) & 0x33) + (n & 0x33);
    n = ((n>>4) & 0x0F) + (n & 0x0F);
    return n;
    }
    u8 CountOnes4 (u16 n) {
    n = ((n>>1) & 0x5555) + (n & 0x5555);
    n = ((n>>2) & 0x3333) + (n & 0x3333);
    n = ((n>>4) & 0x0F0F) + (n & 0x0F0F);
    n = ((n>>8) & 0x00FF) + (n & 0x00FF);
    return n;
    }
    u8 CountOnes4 (u32 n) {
    n = ((n>>1) & 0x55555555) + (n & 0x55555555);
    n = ((n>>2) & 0x33333333) + (n & 0x33333333);
    n = ((n>>4) & 0x0F0F0F0F) + (n & 0x0F0F0F0F);
    n = ((n>>8) & 0x00FF00FF) + (n & 0x00FF00FF);
    n = ((n>>16) & 0x0000FFFF) + (n & 0x0000FFFF);
    return n;
    }
    u8 CountOnes4 (u64 n) {
    n = ((n>>1) & 0x5555555555555555llu) + (n & 0x5555555555555555llu);
    n = ((n>>2) & 0x3333333333333333llu) + (n & 0x3333333333333333llu);
    n = ((n>>4) & 0x0F0F0F0F0F0F0F0Fllu) + (n & 0x0F0F0F0F0F0F0F0Fllu);
    n = ((n>>8) & 0x00FF00FF00FF00FFllu) + (n & 0x00FF00FF00FF00FFllu);
    n = ((n>>16) & 0x0000FFFF0000FFFFllu) + (n & 0x0000FFFF0000FFFFllu);
    n = ((n>>32) & 0x00000000FFFFFFFFllu) + (n & 0x00000000FFFFFFFFllu);
    return n;
    }
    На этом параллельное суммирование не заканчивается. Развить идею позволяет то наблюдение, что в каждой строчке дважды используется одна и та же битовая маска, что как будто наводит на мысль «а нельзя ли как-нибудь только один раз выполнить побитовое «И»?». Можно, но не сразу. Вот что можно сделать, если взять в качестве примера код для u32 (смотрите комментарии).
    u8 CountOnes4 (u32 n) {
    n = ((n>>1) & 0x55555555) + (n & 0x55555555); // Можно заменить на разность
    n = ((n>>2) & 0x33333333) + (n & 0x33333333); // Нельзя исправить
    n = ((n>>4) & 0x0F0F0F0F) + (n & 0x0F0F0F0F); // Можно вынести & за скобку
    n = ((n>>8) & 0x00FF00FF) + (n & 0x00FF00FF); // Можно вынести & за скобку
    n = ((n>>16) & 0x0000FFFF) + (n & 0x0000FFFF); // Можно вообще убрать &
    return n; // Неявное обрезание по 8-и младшим битам.
    }
    В качестве упражнения я бы хотел предложить доказать самостоятельно то, почему нижеследующий код будет точным отображением предыдущего. Для первой строки я даю подсказку, но не смотрите в неё сразу:

  7. Ангел в цепях Ответить

    Ты будешь удивлен, но байты бывают и 5-тибитные, и 7-мибитные, и, даже, 10-битные. В последнее время 8-мибитные – это неписаный стандарт.
    Байт (англ. byte) — единица измерения количества информации, обычно равная восьми битам (в этом случае может принимать 256 (28) различных значений) .
    Вообще, байт — это минимально адресуемая последовательность фиксированного числа битов. В современных компьютерах общего назначения байт равен 8 битам. Для того, чтобы подчеркнуть, что имеется в виду восьмибитный байт, в описании сетевых протоколов используется термин «октет» (лат. octet).
    Иногда байтом называют последовательность битов, которые составляют подполе слова (хотя правильней это называть машинным словом а не байтом) . На некоторых компьютерах возможна адресация байтов разной длины. Это предусмотрено инструкциями извлечения полей ассемблеров LDB и DPB на PDP-10 и в языке Common Lisp.
    В IBM-1401 байт был равен 6 битам так же, как и в Минск-32, а в БЭСМ — 7 битам, в некоторых моделях ЭВМ производства Burroughs Computer Corporation (ныне Unisys) — 9 битам. Во многих современных цифровых сигнальных процессорах используется байт длиной 16 бит и больше.
    Название было впервые использовано в 1956 году В. Бухгольцем при проектировании первого суперкомпьютера IBM 7030 для пучка одновременно передаваемых в устройствах ввода-вывода битов (шести штук) , позже в рамках того же проекта расширили байт до восьми (28) бит.
    Кратные приставки для образования производных единиц для байта применяются не как обычно: во-первых, уменьшительные приставки не используются совсем, а единицы измерения информации меньшие чем байт называются специальными словами (ниббл и бит) ; во-вторых, увеличительные приставки означают за каждую тысячу 1024=210 (килобайт равен 1024 байтам, мегабайт равен 1024 килобайтам, или 1 048 576 байтам; и т. д. с гига-, тера- и петабайтами (больше пока не употребляются)) . Разница возрастает с ростом веса приставки. Более правильно использовать двоичные приставки, но на практике они пока не применяются, возможно, из-за неблагозвучности — кибибайт, мебибайт и т. п.
    Иногда десятичные приставки используются и в прямом смысле, например, при указании ёмкости жёстких дисков: у них гигабайт может обозначать миллион кибибайт, т. е. 1 024 000 000 байтов, а то и просто миллиард байт, а не 1 073 741 824 байта, как, например, в модулях памяти; а так же при указании пропускной способности каналов передачи данных (сетей) .

  8. VideoAnswer Ответить

Добавить ответ

Ваш e-mail не будет опубликован. Обязательные поля помечены *