Como os bits são armazenados na memória? (Em pedaços? Pode haver pedaços de vários tamanhos armazenados para TOGHTER?)

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

Pergunta

Eu costumava pensar que cada local de memória contém 8, 16, 32 ou 64 bits. Portanto, 0101 seria armazenado em uma máquina de 8 bits como 00000101 (o sinal estendido se fosse negativo). Tudo isso foi bom e elegante até que eu escrevi um programa em Java por curiosidade para descobrir mais um trabalho mais interno desse sistema.

O método em questão é assim:

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);}
 }

Eu obtive esta saída de um arquivo que diz olá mundo

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

Tudo isso parece bom, exceto pelo espaço. Ele tem 6 bits em vez de 8. Agora estou me perguntando como todas essas informações são armazenadas na memória. Se tudo foi armazenado em pedaços de 8 bits, como

Olá: 1001000110010111011001101100110111111

Em seguida, você pode simplesmente olhar para cada pedaço de 8 bits e descobrir qual número ele está representando (e depois a que código ASCII se refere). Como funciona quando um personagem de tamanho diferente (como o espaço de 6 bits e o 4 bits /n) é armazenado junto com eles? Então não armazenaria um pequeno número em um grande espaço desperdiçado de muitos pedaços?

Eu acho que tenho um pouco do entendimento fundamental errado (ou talvez o programa esteja errado em algum lugar ...). Desculpe se a pergunta soa estranha ou muito desconhecida em profundidade. Eu só quero saber. Eu fiz um pouco de Google, mas não criou nada relevante. Se você puder me informar onde eu dava errado ou me indico na direção certa, eu agradeço muito. Obrigado!

Foi útil?

Solução

Você será melhor experimentar em C e/ou montagem, em vez de Java. Esses idiomas são de nível inferior e exponham o espaço de endereço diretamente.

Eu costumava pensar que cada local de memória contém 8, 16, 32 ou 64 bits. Portanto, 0101 seria armazenado em uma máquina de 8 bits como 00000101 (o sinal estendido se fosse negativo). Tudo isso foi bom e elegante até que eu escrevi um programa em Java por curiosidade para descobrir mais um trabalho mais interno desse sistema.

Todos os locais de memória nos sistemas x86 contêm 8 bits (1 byte). Se um valor contiver mais dados do que pode se encaixar em um byte único, ele será armazenado usando vários bytes. Por exemplo, em C, o tipo "float" é armazenado usando 4 bytes (32 bits).

Tudo isso parece bom, exceto pelo espaço. Ele tem 6 bits em vez de 8. Agora estou me perguntando como todas essas informações são armazenadas na memória. Se tudo foi armazenado em pedaços de 8 bits, como

O espaço também é armazenado em um único byte. Seu código de impressão está esquecendo de chegar a 8 espaços. 100000 == 00100000 == 0x20.

Outras dicas

O espaço também tem 8 bits. É só que o número inteiro.TobinaryString não imprime liderança 0 Bits da maneira como você o usou.

Com toda a liderança 0 Bits, na verdade se parece com isso na memória:

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

Sua intuição original estava (principalmente) correta: todos os locais de memória consistem no mesmo número de bits. Em todas as máquinas modernas, existem oito bits em um "byte", onde um byte é o menor pedaço de memória que a máquina pode acessar individualmente.

Olhe de perto a sua saída. Você tem Sete dígitos em todos eles, exceto o espaço. O espaço começa com dois zeros em sua representação binária, enquanto as outras letras começam com uma.

Na verdade, sua abordagem está errada. A codificação é muito importante aqui.

Se você usa ASCII, poderá dizer facilmente que cada caractere é armazenado em um byte (oito bits), mas ao codificar mudanças, você não pode dizer isso.

Por exemplo: o UTF-8 usa um a três bytes (8 a 24 bits) para cada caractere em uma string. É por isso que você verá uma sobrecarga na qual pode especificar a codificação no objeto InputStream.

Escolher o fluxo de entrada errado causará absolutamente uma saída de string errada. Assim, você precisa saber a codificação do arquivo para entender qual bit significa o quê. Na verdade, o FileInputStream faz isso por você.

Se você armazenar um dígito como string, ele terá um comprimento de carvão no disco rígido. Assim como outro personagem.

No entanto, se você armazenar 123456789 como string com a codificação ASCII, ele levará 9*8 bits = 72 bits.

Se você armazenar isso como número inteiro (observe que a largura dos dados do número inteiro difere em diferentes ambientes), levará apenas 16 bits.

Também você não pode ter certeza disso

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

é armazenado no disco rígido como H: 01001000 E: 01100101 L: 01101100 L: 01101100 O: 0110111111: 00100000 W: 01010111 O: 01101111 R: 01110010 L: 01101100 D: 01100100 n: 00101010101010

Você não pode ter certeza disso. O sistema de arquivos não é tão simples. Talvez o olá seja sucessivo, mas o World String está no final do Drive. É por isso que há comando desfrag.

Mas se falarmos sobre a memória principal (RAM) quando você definir uma corda, espero que os bits sejam sucessivos. Pelo menos em C é. Você define uma corda como essa.

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

Aqui o valor [0] é o primeiro caractere da nossa string. E o valor se endereça apenas ao local das matrizes de char na memória.

Se o endereço do valor [0] for 10, o endereço do valor [1] é 10+8 = 18.

A maneira como os computadores armazenam números podem ser comparados a um odômetro em um carro. Se o odômetro tiver 4 dígitos, ele armazena o número 33 como "0033".

Se alguém pergunta Você é o que é sua milhagem, você não vai dizer "zero mil zero cento e trinta e três". Por padrão, Java também não. (Embora você possa dizer isso.)

Então não armazenaria um pequeno número em um grande espaço desperdiçado de muitos pedaços?

Bem, na verdade não. Suponha que você tenha 11000100 na memória em algum lugar. Como o computador deve saber se isso significa 11000100 ou 11000 seguidos por 100, ou 1, seguido por 1000 seguidos por 100, e assim por diante?

Bem, na verdade, o computador está apenas seguindo o programa (lembre -se de que um programa Java é criado em parte por você e em parte pelas pessoas que projetam Java). Se você pode criar um sistema viável para salvar bits, poderá fazer o computador fazê -lo.

No entanto, lembre -se de que há uma troca em termos de uso de processadores e dificuldade de programação. Como um computador típico pode funcionar com bytes Muito de Mais rapidamente do que pode, digamos, números de 7 bits ou variáveis, armazenar códigos ASCII em bytes é uma opção muito comum para armazenar texto.

Mas deixe -me voltar à sua pergunta.

Então não armazenaria um pequeno número em um grande espaço desperdiçado de muitos pedaços?

Matematicamente falando, não. Um ramo da matemática chamado Teoria da informação nos diz que o número de bits que são absolutamente necessários depende das possibilidades que você deseja codificar e qual a probabilidade de cada um deles.

Suponhamos que você tenha apenas um alfabeto de quatro letras (A, B, C, D) e use números de dois bits (00, 01, 10, 11, respectivamente) para representá-lo. Se cada uma dessas letras for igualmente provável, o número mínimo de bits exigidos por letra (em média) é 2. Em outras palavras, existem não Bits desperdiçados, embora A IS 00 e B seja 01.

Por outro lado, se você usar ascii e codificar A, B, C, D como os seguintes números de 7 bits:

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

Então você está "desperdiçando" 5 bits por letra (mesmo que você não esteja "armazenando pequenos números em um grande espaço").

Esses tipos de considerações são importantes ao projetar algoritmos de compressão e não são tão importantes para os aplicativos para todos os dias. Certamente é importante entender bits e bytes, se você deseja aprender C.

De acordo com Java 4 API,

O valor inteiro não assinado é o argumento mais 232 se o argumento for negativo; Caso contrário, é igual ao argumento. Este valor é convertido em uma sequência de dígitos ASCII em binário (Base 2), sem líderes extras.

Na realidade, o armazenamento de dados é realmente muito mais complicado. Para eficiências no processamento, a maioria dos tipos de dados é armazenada em limites de palavras, o que significa 4 bytes em máquinas de 32 bits ou 8 bytes em máquinas de 64 bits. Matrizes podem ser embaladas mais de perto, para que char [4] pode acabar usando a mesma quantidade de "espaço real" que char.

O Java é uma máquina virtual, e não tenho certeza de qual arquitetura de memória, se houver, ela usa.

Isso esclarece. Meu principal problema era que eu estava ignorando os zeros no começo. Eu estava experimentando isso enquanto estava lendo mais sobre algoritmos de compressão (a saber, GZIP), estava assumindo ASCII por tudo isso. Ver a representação não era o objetivo do programa, mas o número diferente de bits por palavra me expulsou do objetivo original de implementar uma compactação básica baseada em índice para um tipo de arquivo em que estou trabalhando. Vou tentar reescrevê -lo em C assim que tiver uma prova de conceito em Java.

Obrigado!

http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/integer.html#tobinarystring%28int%29
A especificação do Integer.Tobinarys lê:

"Este valor é convertido em uma sequência de dígitos ASCII em binário (base 2), sem os principais 0s"

Que você ignorou esse fato é o que levou à sua confusão.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top