Por que caracteres em inglês exigem menos bytes para representar do que outros alfabetos?

31

Quando coloco 'a' em um arquivo de texto, ele produz 2 bytes, mas quando coloco, digamos 'ա', que é uma letra do alfabeto armênio, produz 3 bytes.

Qual é a diferença entre alfabetos para um computador?
Por que o inglês ocupa menos espaço?

khajvah
fonte
22
Você deve ler este artigo do fundador do StackExchange: joelonsoftware.com/articles/Unicode.html
Eric Lippert
22
Eu não acho que exista algo como "caracteres em inglês". Eles são romanos.
Raphael
5
@ Rafael Todo mundo sabe o que ele está se referindo embora. Mas bom adicionar.
Mathias Lykkegaard Lorenzen 12/04
1
@Raphael Na verdade, existem muitas letras romanas que não são usadas em inglês e, portanto, não estão incluídas no conjunto de caracteres ASCII. A maioria deles inclui modificadores, mas ainda são necessários para renderizar corretamente o texto em vários idiomas derivados do latim, além do inglês.
Wutaz
7
@Raphael Eu não acho que exista algo como "caracteres romanos". Eles são latinos.
Blacklight Shining

Respostas:

41

Um dos primeiros esquemas de codificação a serem desenvolvidos para uso em computadores convencionais é o padrão ASCII ( American Standard Code for Information Interchange ). Foi desenvolvido na década de 1960 nos Estados Unidos.

O alfabeto inglês usa parte do alfabeto latino (por exemplo, existem poucas palavras acentuadas em inglês). Existem 26 letras individuais nesse alfabeto, sem considerar o caso. E também teria que existir os números e sinais de pontuação individuais em qualquer esquema que pretenda codificar o alfabeto inglês.

A década de 1960 também foi uma época em que os computadores não tinham a quantidade de memória ou espaço em disco que temos agora. O ASCII foi desenvolvido para ser uma representação padrão de um alfabeto funcional em todos os computadores americanos. Na época, a decisão de fazer com que todos os caracteres ASCII tivessem 8 bits (1 byte) de comprimento foi tomada devido a detalhes técnicos da época (o artigo da Wikipedia menciona o fato de que a fita perfurada mantinha 8 bits em uma posição por vez). De fato, o esquema ASCII original pode ser transmitido usando 7 bits, os oito podem ser usados ​​para verificações de paridade. Desenvolvimentos posteriores expandiram o esquema ASCII original para incluir vários caracteres acentuados, matemáticos e terminais.

Com o recente aumento do uso de computadores em todo o mundo, mais e mais pessoas de diferentes idiomas tiveram acesso a um computador. Isso significava que, para cada idioma, novos esquemas de codificação tinham que ser desenvolvidos, independentemente de outros esquemas, que entrariam em conflito se lidos em terminais de idiomas diferentes.

O Unicode surgiu como uma solução para a existência de diferentes terminais, mesclando todos os caracteres significativos possíveis em um único conjunto de caracteres abstratos.

UTF-8 é uma maneira de codificar o conjunto de caracteres Unicode. É uma codificação de largura variável (por exemplo, caracteres diferentes podem ter tamanhos diferentes) e foi projetada para compatibilidade retroativa com o antigo esquema ASCII. Como tal, o conjunto de caracteres ASCII permanecerá com um byte grande, enquanto outros caracteres terão dois ou mais bytes. UTF-16 é outra maneira de codificar o conjunto de caracteres Unicode. Em comparação com UTF-8, os caracteres são codificados como um conjunto de uma ou duas unidades de código de 16 bits.

Conforme declarado nos comentários, o caractere 'a' ocupa um único byte enquanto 'ա' ocupa dois bytes, denotando uma codificação UTF-8. O byte extra na sua pergunta ocorreu devido à existência de um caractere de nova linha no final (sobre o qual o OP descobriu).

Doktoro Reichard
fonte
26
Não há último byte que codifique o final do arquivo, em qualquer codificação ou formato de arquivo normal. Quando um programa lê um arquivo, o final do arquivo pode ser sinalizado pelo SO de uma maneira especial, mas essa é uma questão diferente.
Jukka K. Korpela
2
O caractere is tem 2 bytes (0xD5A1) na versão UTF-8 do unicode; o caractere extra (seja o que for) está presente nos dois arquivos. marathon-studios.com/unicode/U0561/Armenian_Small_Letter_Ayb
Dan Neely
6
@khajvah Se você echo 'ա' > file.txto editar ou editar usando alguns editores, eles adicionarão automaticamente uma nova linha após ela. Se você executar xxd file.txt, o último byte provavelmente será um 0afeed de linha.
Daniel Beck
7
@DoktoroReichard: Esclareça na resposta que o Unicode não é uma codificação; em vez disso, é um conjunto de caracteres abstratos, e UTF-16 e UTF-8 são codificações de pontos de código Unicode. Os últimos parágrafos de sua resposta falam principalmente sobre UTF-8. Porém, se um arquivo usa UTF-16, qualquer ponto de código, mesmo aquele para a, usará dois bytes (ou um múltiplo de dois).
grawity
6
Também provavelmente vale a pena enfatizar que os conjuntos de caracteres "ASCII estendido" não são de fato ASCII, e o número de maneiras diferentes de utilizar o oitavo bit torna tudo uma grande bagunça. Basta usar UTF-8.
Ntskrnl 11/04
17

1 byte é 8 bits e, portanto, pode representar até 256 (2 ^ 8) valores diferentes.

Para idiomas que exigem mais possibilidades do que isso, um mapeamento simples de 1 para 1 não pode ser mantido; portanto, são necessários mais dados para armazenar um caractere.

Observe que, geralmente, a maioria das codificações usa os primeiros 7 bits (128 valores) para caracteres ASCII . Isso deixa o oitavo bit, ou 128 mais valores para mais caracteres. . . adicione caracteres acentuados, idiomas asiáticos, cirílico etc., e você poderá ver facilmente por que 1 byte não é suficiente para manter todos os caracteres.

Ernie
fonte
então aqui é a única resposta realmente explicar por que mais espaço é usado
Félix Gagnon-Grenier
10

No UTF-8, os caracteres ASCII usam um byte, outros caracteres usam dois, três ou quatro bytes.

Jason
fonte
1
Você pode explicar por que isso acontece? observar dois métodos de codificação não responde bem à pergunta.
precisa saber é
O @MaQleod Unicode foi criado para substituir o ASCII. Para compatibilidade com versões anteriores, os primeiros 128 caracteres são os mesmos. Esses 128 caracteres podem ser expressos com um byte. Bytes adicionais são adicionados para caracteres adicionais.
Jason
Estou ciente, mas isso faz parte da resposta à pergunta sobre o que torna os caracteres ASCII diferentes. Isso deve ser explicado ao PO.
precisa saber é
@MaQleod Também se pode dizer que o Unicode Consortium era formado principalmente por empresas americanas e era tendencioso em relação aos caracteres do idioma inglês. Eu pensei que uma resposta simples era melhor do que subjetiva.
Jason
15
Não "em Unicode", em UTF8 - que é apenas uma das várias codificações do conjunto de caracteres Unicode.
Sebastian Negraszus
3

A quantidade de bytes necessários para um caractere (sobre o qual a pergunta é aparentemente) depende da codificação de caracteres. Se você usar a codificação ArmSCII, cada letra armênia ocupa apenas um byte. Hoje em dia, não é uma boa escolha.

Na codificação de transferência UTF-8 para Unicode, os caracteres precisam de um número diferente de bytes. Nele, “a” ocupa apenas um byte (a idéia de dois bytes é uma espécie de confusão), “á” ocupa dois bytes e a letra armênia ayb “ա” também ocupa dois bytes. Três bytes devem ser algum tipo de confusão. Por outro lado, por exemplo, a letra bengali a “অ” ocupa três bytes em UTF-8.

O pano de fundo é simplesmente que o UTF-8 foi projetado para ser muito eficiente para caracteres Ascii, bastante eficiente para sistemas de escrita na Europa e arredores e todo o resto é menos eficiente. Isso significa que, em letras latinas básicas (que é basicamente o texto em inglês), é necessário apenas um byte para um caractere; para grego, cirílico, armênio e alguns outros, são necessários dois bytes; todo o resto precisa de mais.

O UTF-8 possui (como apontado em um comentário) também a propriedade útil de que os dados Ascii (quando representados como unidades de 8 bits, que são quase a única maneira há muito tempo) também são trivialmente codificados por UTF-8.

Jukka K. Korpela
fonte
Obrigado pela resposta. Bytes adicionais são porque o programa que eu usei adicionou automaticamente um novo caractere de linha ao final.
Khajvah
1
Não acho que o UTF-8 tenha sido projetado tanto para eficiência com dados ASCII quanto para compatibilidade . O UTF-8 possui a propriedade muito boa de que o conteúdo ASCII de 7 bits (com o bit alto definido como zero) é idêntico ao mesmo conteúdo codificado como UTF-8, portanto, para ferramentas que normalmente lidam com ASCII, é uma substituição imediata . Nenhum outro esquema de codificação Unicode possui essa propriedade, que eu saiba. O UTF-8 também é razoavelmente compacto para a maioria dos dados, principalmente se você permanecer dentro do domínio do Unicode BMP .
um CVn
1
@ MichaelKjörling, adicionei uma referência a esse recurso. No entanto, uma das principais objeções ao Unicode nos primeiros dias era a ineficiência, e o UTF-16 dobra o tamanho dos dados que são predominantemente Ascii. UTF-8 significa, por exemplo, para texto em inglês, que você "paga" apenas pelos caracteres não-Ascii que usa.
Jukka K. Korpela
3

Os códigos de caracteres na década de 1960 (e muito além) eram específicos da máquina. Nos anos 80, usei brevemente uma máquina DEC 2020, que tinha 36 bits de palavras e 5, 6 e 8 ( IIRC ) bits por codificação de caracteres. Antes disso, usei uma série IBM 370 com EBCDIC. O ASCII com 7 bits trouxe ordem, mas causou confusão com as "páginas de código" do IBM PC usando todos os 8 bits para representar caracteres extras, como todo tipo de desenho de caixa para pintar menus primitivos e extensões ASCII posteriores, como o Latin-1 (8 bits). codificações, com os primeiros 7 bits como ASCII e a outra metade para "caracteres nacionais" como ñ, Çou outros. Provavelmente o mais popular foi o Latin-1, adaptado ao inglês e à maioria dos idiomas europeus usando caracteres latinos (e sotaques e variantes).

Escrever texto misturando, por exemplo, inglês e espanhol correu bem (basta usar o latim-1, superconjunto de ambos), mas misturar qualquer coisa que usasse codificações diferentes (por exemplo, incluir um trecho de grego ou russo, sem mencionar um idioma asiático como o japonês) foi um verdadeiro pesadelo. O pior foi que o russo, principalmente o japonês e o chinês, possuíam várias codificações populares e completamente incompatíveis.

Hoje usamos Unicode, que é acoplado a codificações eficientes como UTF-8 que favorecem caracteres em inglês (surpreendentemente, a codificação de letras em inglês corresponde a ASCII), fazendo com que muitos caracteres que não sejam do inglês usem codificações mais longas.

vonbrand
fonte
2

Arquivo em inglês / americano do Windows 8.1 com um único 'a' salvo no bloco de notas.

  • Salvar AS ANSI 1 byte
  • Salvar AS Unicode 4 bytes
  • Salvar AS UTF-8 4 bytes

Arquivo com um único 'ա' salvo com o bloco de notas

  • Salvar AS ANSI não é possível
  • Salvar AS Unicode 4 bytes
  • Salvar AS UTF-8 5 bytes

Um único 'a' é codificado como um byte único no ANSI; no Unicode, cada caractere geralmente tem 2 bytes; também há uma lista técnica de 2 bytes no início do arquivo. O UTF-8 possui uma lista técnica de 3 bytes e o caractere de byte único.

Para o 'ա', esse caractere não existe no conjunto de caracteres ANSI e não pode ser salvo na minha máquina. O arquivo Unicode é o mesmo de antes e o arquivo UTF-8 é 1 byte maior, pois o caractere leva 2 bytes.

Se a sua máquina for de uma região diferente, você pode ter uma página de código OEM diferente instalada, com glifos diferentes para os 255 caracteres possíveis no intervalo ASCII. Como o @ntoskrnl mencionou, a página de códigos OEM da minha máquina seria Windows-1252, que é o padrão para o inglês dos EUA.

Darryl Braaten
fonte
4
O bloco de notas (e o Windows em geral) usa terminologia confusa aqui. "ANSI" é uma codificação de byte único dependente da localidade (Windows-1252 em versões em inglês) e "Unicode" é UTF-16.
Ntskrnl 11/04
@ntoskrnl Isso está correto, mas se você estiver procurando na codificação, ele diz ANSI, razão pela qual mencionei que se você tiver uma página de código OEM diferente, poderá obter resultados diferentes.
precisa saber é o seguinte
2

Se você estiver interessado em saber como os caracteres são armazenados, acesse www.unicode.org e dê uma olhada. No topo da página principal, há um link "Gráficos de códigos" que mostra todos os códigos de caracteres disponíveis no Unicode.

Em suma, há um pouco mais de um milhão de códigos disponíveis no Unicode (nem todos são usados). Um byte pode conter 256 valores diferentes; portanto, você precisará de três bytes se desejar armazenar todos os códigos Unicode possíveis.

Em vez disso, o Unicode geralmente é armazenado na codificação "UTF-8", que usa menos bytes para alguns caracteres e mais para outros. Os primeiros 128 valores de código são armazenados em um único byte, até os primeiros valores de código 2048 são armazenados em dois bytes, até 65536 são armazenados em três bytes e o restante ocupa quatro bytes. Isso foi organizado para que os valores de código usados ​​com mais frequência ocupem menos espaço. AZ, az, 0-9 e! @ $% ^ & * () - [} {}; ': "|,. / <>? E alguns que eu esqueci de usar um byte; quase todo o inglês, 98% de Alemão e francês (apenas adivinhando) podem ser armazenados em um byte por caractere, e esses são os caracteres mais usados: cirílico, grego, hebraico, árabe e outros usam dois bytes por caractere. , Coreano, tailandês, toneladas de símbolos matemáticos, pode ser escrito em três bytes por caractere. Coisas raras (se você quiser escrever texto em Linear A ou Linear B, Emojis) levam quatro bytes.

Outra codificação é UTF-16. Tudo o que leva 1, 2 ou 3 bytes em UTF-8 leva dois bytes em UTF-16. Essa é uma vantagem se você tiver texto em chinês ou japonês com muito poucos caracteres latinos no meio.

Sobre os motivos do design UTF-8: Possui várias vantagens sobre outros designs. Eles são:

Compatibilidade com caracteres US-ASCII

Compacidade razoável

Auto-sincronização: Isso significa que, se você receber parte de uma sequência de bytes que são caracteres na codificação UTF-8, poderá descobrir onde os caracteres são iniciados. Em algumas codificações, xy e yx podem ser codificações válidas de caracteres, portanto, se você receber parte de uma sequência ... xyxyxyxyxyxy ... não poderá saber quais caracteres você possui.

Correção da classificação: se você classificar cadeias contendo caracteres codificados em UTF-8 pelos valores de bytes, elas serão automaticamente classificadas corretamente de acordo com os valores Unicode.

Compatível com código de byte único: a maioria dos códigos que assumem valores de byte único funciona automaticamente corretamente com caracteres codificados em UTF-8.

Além disso, por qualquer motivo que eu tenha esquecido.

gnasher729
fonte