Как биты хранятся в памяти?(кусками?Могут ли храниться вместе биты разных размеров?)

StackOverflow https://stackoverflow.com/questions/1546381

Вопрос

Раньше я думал, что каждая ячейка памяти содержит 8, 16, 32 или 64 бита.Таким образом, 0101 будет храниться в 8-битной машине как 00000101 (знак расширяется, если он отрицательный).Все было прекрасно, пока я не написал программу на Java из любопытства, чтобы узнать больше о внутренней работе этой системы.

Рассматриваемый метод выглядит следующим образом:

public void printBinaryRep(File f){
        try{
            FileInputStream inputStream = new FileInputStream(f);
            int next = 0;
            byte b = 0;
            while((next = inputStream.read()) != -1){
                b = (byte)next;
                System.out.println((char)next + " : "+Integer.toBinaryString(next));
            }
            inputStream.close();
        }
        catch(Exception e){System.out.println(e);}
 }

Я получил этот вывод из файла с надписью Hello World.

H : 1001000
e : 1100101
l : 1101100
l : 1101100
o : 1101111
  : 100000
W : 1010111
o : 1101111
r : 1110010
l : 1101100
d : 1100100

Все выглядит хорошо, кроме места.Там 6 бит вместо 8.Теперь мне интересно, как вся эта информация хранится в памяти.Если бы все это хранилось в 8-битных кусках, например

Привет:10010001100101110110011011001101111

Затем вы можете просто посмотреть на каждый 8-битный фрагмент и выяснить, какое число оно представляет (а затем, к какому коду ASCII оно относится).Как это работает, когда вместе с ними хранится символ другого размера (например, 6-битное пространство и 4-битный /n)??Тогда не приведет ли хранение небольшого числа в большом битовом пространстве к потере большого количества битов?

Я думаю, что у меня неправильное понимание некоторых фундаментальных вопросов (или, может быть, где-то ошибается программа...).Извините, если вопрос звучит странно или слишком глубоко.Я просто хочу знать.Я немного погуглил, но ничего путного не нашел.Если вы сообщите мне, где я ошибся, или направите меня в правильном направлении, я буду очень признателен.Спасибо!

Это было полезно?

Решение

Вам будет лучше экспериментировать в C и/или сборке, а не на Java. Эти языки являются более низким уровнем и непосредственно обнажают адресное пространство.

Раньше я думал, что каждое местоположение памяти содержит 8, 16, 32 или 64 бит. Таким образом, 0101 будет храниться в 8 -битной машине как 00000101 (знак расширен, если он был отрицательным). Это было хорошо и тщательно, пока я не написал программу в Java из любопытства, чтобы узнать еще немного внутренней работы этой системы.

Все места памяти в системах x86 содержат 8 бит (1 байт). Если значение содержит больше данных, чем может соответствовать одному байту, оно хранится с использованием нескольких байтов. Например, в C тип «float» сохраняется с использованием 4 байтов (32 бита).

Все это выглядит нормально, за исключением пространства. Он имеет 6 бит вместо 8. Теперь мне интересно, как вся эта информация хранится в памяти. Если все это хранилось в 8 -битных кусках, как

Пространство также хранится в одном байте. Ваш код печати забывает набрать до 8 мест. 100000 == 00100000 == 0x20.

Другие советы

Пространство тоже имеет 8 бит. Это просто целое число. 0 Биты так, как вы его использовали.

Со всеми ведущими 0 Биты, на самом деле это выглядит в памяти:

H : 01001000
e : 01100101
l : 01101100
l : 01101100
o : 01101111
  : 00100000
W : 01010111
o : 01101111
r : 01110010
l : 01101100
d : 01100100

Ваша первоначальная интуиция была (в основном) правильной: все места памяти состоят из одинакового количества битов. На всех современных машинах в «байте» есть восемь битов, где байт - это самый маленький кусок памяти, к которому машина может получить доступ к индивидуально.

Посмотрите внимательно на свой вывод. У вас есть Семь цифры во всех из них, кроме пространства. Пространство только начинается с двух нулей в его двоичном представлении, в то время как другие буквы начинаются с одного.

На самом деле ваш подход неправильный.Кодирование здесь очень важно.

Если вы используете ASCII, вы можете легко сказать, что каждый символ хранится в байте (восемь бит), но при изменении кодировки вы не можете этого сказать.

Например:UTF-8 использует от одного до трех байтов (от 8 до 24 бит) для каждого символа строки.Вот почему вы увидите перегрузку, в которой вы можете указать кодировку объекта входного потока.

Выбор неправильного входного потока абсолютно приведет к неправильному выводу строки.Таким образом, вам нужно знать кодировку файла, чтобы понять, какой бит что означает.На самом деле fileinputstream сделает это за вас.

Если вы сохраните цифру в виде строки, она займет длину символа на жестком диске.Как и другой персонаж.

Однако если вы сохраните 123456789 как строку с кодировкой ASCII, это займет 9 * 8 бит = 72 бита.

Если вы сохраните это как целое число (обратите внимание, что ширина данных целого числа различается в разных средах), это займет всего 16 бит.

Также вы не можете быть уверены, что

H : 01001000
e : 01100101
l : 01101100
l : 01101100
o : 01101111
  : 00100000
W : 01010111
o : 01101111
r : 01110010
l : 01101100
d : 01100100
\n: 00001010

хранится на жестком диске как H:01001000 e:01100101 л:01101100 л:01101100 o:01101111 :00100000 W:01010111 o:01101111 r:01110010 л:01101100 d:01100100 :00001010

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

Но если мы говорим об основной памяти (ОЗУ), когда вы определяете строку, я ожидаю, что биты будут последовательными.По крайней мере, в C это так.Вы определяете такую ​​​​строку.

char[100] value; // c is a char array. (there is no string type in c)

здесь value[0] — первый символ нашей строки.И значение обращается только к местоположению массива символов в памяти.

если адрес value[0] равен 10, то адрес value[1] равен 10+8 = 18.

То, как компьютеры хранят номера, можно сравнить с одомером в автомобиле. Если одометр имеет 4 цифры, он хранит номер 33 как «0033».

Если кто-нибудь спрашивает Вы, каков ваш пробег, вы не скажете «нулевые тысячи нулевых сотни тридцати трех». По умолчанию Java тоже нет. (Хотя вы можете сказать это.)

Тогда не будет ли хранить небольшое количество в большом пространстве тратить много кусочков?

Ну не совсем. Предположим, у вас где -то было 11000100 в памяти. Как компьютер должен знать, означает ли это 11000100 или 11000, за которым следует 100, или 1, за которым следует 1000 с последующим 100, и т. Д.?

Что ж, на самом деле компьютер просто следит за программой (помните, что программа Java создается частично вами, а отчасти людьми, которые разрабатывают Java). Если вы можете создать жизнеспособную систему для сохранения битов, вы можете заставить компьютер сделать это.

Тем не менее, имейте в виду, что есть компромисс с точки зрения использования процессора и сложности программирования. Поскольку типичный компьютер может работать с байтами много быстрее, чем можно, скажем, с 7-битными или переменными числами, хранение кодов ASCII в байтах является очень распространенным выбором для хранения текста.

Но позвольте мне вернуться к вашему вопросу.

Тогда не будет ли хранить небольшое количество в большом пространстве тратить много кусочков?

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

Предположим, у вас есть только четырехбуктный алфавит (A, B, C, D) и используйте двухбитные числа (00, 01, 10, 11 соответственно), чтобы представлять его. Если каждая из этих букв в равной степени вероятно, то минимальное количество битов, необходимых для буквы (в среднем), 2. Другими словами, есть нет Потраченные биты, хотя a 00, а B - 01.

С другой стороны, если вы используете ASCII и кодируете A, B, C, D в качестве следующих 7-битных чисел:

A: 1000001
B: 1000010
C: 1000011
D: 1000100

Тогда вы «тратите» 5 бит на букву (даже если вы не «храните небольшие цифры в большом пространстве»).

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

Согласно Java 4 API,

Неподписанное целое число - это аргумент плюс 232, если аргумент отрицательный; в противном случае это равно аргументу. Это значение преобразуется в строку цифр ASCII в бинарном (базе 2) без дополнительного ведущего 0s.

В действительности, хранение данных на самом деле намного сложнее. Для эффективности в обработке большинство типов данных хранятся в слоях, что означает 4 байта на 32-битных машинах, или 8 байтов на 64-битных машинах. Массивы могут быть упакованы более близко, чтобы char [4] может в конечном итоге использовать то же количество «фактического пространства», что и char.

Java - это виртуальная машина, и я не уверен, какая архитектура памяти, если таковая имеется, она использует.

Это очищает это. Моя главная проблема заключалась в том, что в начале я упускал из виду нули. Я экспериментировал с этим, когда читал больше об алгоритмах сжатия (а именно, GZIP), я предполагал ASCII для всего этого. Видение представления не было целью программы, но различное количество битов на слово отбросило меня от первоначальной цели в реализации основного сжатия на основе индекса для типа файла, над которым я работаю. Я постараюсь переписать его в C, как только у меня появится доказательство концепции на Java.

Спасибо!

http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/integer.html#tobinarystring%28int%29
Спецификация Integer.Tobinarys читает:

«Это значение преобразуется в строку цифр ASCII в двоичном (базе 2) без дополнительного ведущего 0s»

То, что вы упустили из виду этот факт, это привело к вашей путанице.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top