Как буквы в верхнем и нижнем регистре отличаются только одним битом?

Я нашел один пример в книге "Сеть данных и коммуникаций", написанной Бехрузой Форозаном в отношении букв верхнего и нижнего регистра, которые отличаются только одним битом в 7-битном коде.

Например, символ A равен 1000001 (0x41), а символ a равен 1100001 (0x61). Разница заключается в бит 6, который равен 0 в прописных и 1 строчными буквами. Если мы знаем код для одного случая, мы можем легко найти код для другого, добавив или вычитая 32 в десятичном значении, или просто перевернем шестой бит.

Что все это значит?

Я очень смутился со всеми этими вещами. Может ли кто-нибудь привести примеры того, как эти вещи действительно работают?

Ответы

Ответ 1

Позвольте использовать случай, который вы найдете более знакомым: base 10.

  • Предположим, что у нас есть компьютер с базой 10, где каждый 10 бит хранит значение от 0 до 9, а 10 байт - 5 10 бит, так что каждый байт может хранить 100 000 значений (от 0 до 99,999).

  • Вы хотите назначить буквы на определенные позиции в 10-битном формате, чтобы этот компьютер мог передавать текстовые данные с других компьютеров. Один из способов сделать это можно сделать так:

    00101 A    00201 a
    00102 B    00202 b
    00103 C    00203 c
    00104 D    00204 d
    00105 E    00205 e
    00106 F    00206 f
    00107 G    00207 g
    00108 H    00208 h
    00109 I    00209 i
    00110 J    00210 j
    00111 K    00211 k
    00112 L    00212 l
    00113 M    00213 m
    00114 N    00214 n
    00115 O    00215 o
    00116 P    00216 p
    00117 Q    00217 q
    00118 R    00218 r
    00119 S    00219 s
    00120 T    00220 t
    00121 U    00221 u
    00122 V    00222 v
    00123 W    00223 w
    00124 X    00224 x
    00125 Y    00225 y
    00126 Z    00226 z
    
  • Видите ли, что каждая строчная буква отличается от буквы верхнего регистра только одной десятичной цифрой, в третьем столбце справа? Это не должно было быть спроектировано таким образом. Это было просто удобно, потому что тогда в любой момент, когда мы хотим скорректировать случай буквы, мы можем просто изменить одну из цифр (10 бит), не заботясь о том, что остальное количество или беспокоит двадцать шесть различных преобразований, когда мы можем это сделать один. Мы не могли бы выбрать вторую цифру, потому что вместо того, чтобы быть на 100 друг от друга, они были бы только 10 друг от друга и перекрывались бы.

  • Теперь, в базе 2, это точно то же самое, но вместо каждого бита, представляющего 0-9, он может представлять только 0-1. Использование восьми 2-битов дает нам всего 256 возможных комбинаций, 0-255. Коды ASCII для букв верхнего и нижнего регистра в двоичном формате выглядят следующим образом:

    01000001 A        01100001 a
    01000010 B        01100010 b
    01000011 C        01100011 c
    01000100 D        01100100 d
    01000101 E        01100101 e
    01000110 F        01100110 f
    01000111 G        01100111 g
    01001000 H        01101000 h
    01001001 I        01101001 i
    01001010 J        01101010 j
    01001011 K        01101011 k
    01001100 L        01101100 l
    01001101 M        01101101 m
    01001110 N        01101110 n
    01001111 O        01101111 o
    01010000 P        01110000 p
    01010001 Q        01110001 q
    01010010 R        01110010 r
    01010011 S        01110011 s
    01010100 T        01110100 t
    01010101 U        01110101 u
    01010110 V        01110110 v
    01010111 W        01110111 w
    01011000 X        01111000 x
    01011001 Y        01111001 y
    01011010 Z        01111010 z
    

    Точно так же, как и раньше, они отличаются только одной 2-битной цифрой, здесь, в шестом столбце справа. Мы не могли бы использовать цифру в любом порядке справа (меньше), потому что тогда списки были бы перекрыты (2 ^ 5 = 32, и соответственно мы использовали все биты от 0 до 5, но 2 ^ 4 = 16, которые не могли покрыть 26 букв алфавита).

  • Просто, чтобы немного рассказать, вот пример того, что означают эти двоичные значения. Возьмем один для G. Чтобы понять, что означает 01000111 в двоичном формате:

     Pos:   7  6  5  4  3  2  1  0
     Bit:   0  1  0  0  0  1  1  1
     Val: 128 64 32 16  8  4  2  1
    Mult:   0 64  0  0  0  4  2  1
     Add: 64 + 4 + 2 + 1 = 71, which is the ASCII code for G.
    

    Выполняя то же самое для буквы G в специальной системе основания 10, которую я построил выше:

      Pos:     4    3    2    1    0
    10Bit:     0    0    1    0    7
      Val: 10000 1000  100   10    1
     Mult:     0    0  100    0    7
      Add: 100 + 7 = 107, which is my special 10ASCII code for G.
    

    Посмотрите на строку "Val" для двоичного кода. Вы видите, что начиная с правой, каждое значение в два раза больше предыдущего? Удваивается каждый раз, когда мы получаем 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 и т.д. Таким образом, двоичная позиция разряда определяет ее значение, точно так же, как позиция десятичной цифры определяет ее значение с полномочиями 10: 1, 10, 100, 1000, 10000, 100000 и т.д.

    Я понимаю, что это кажется глупым, потому что все, что я сделал, было конвертировать от 107 до 107... но 107 - это не просто число, это сокращенная форма для:

    1 hundreds + 0 tens + 7 ones.
    

    Другим способом, который мы могли бы представить, является

    0 x 10^4 + 0 x 10^3 + 1 x 10^2 + 0 x 10^1 + 7 x 10^0.
    

    Аналогично, 01000111 - это не просто двоичное число, это сокращенная форма для

    0 x 2^7 + 1 x 2^6 + 0 x 2^5 + 0 x 2^4 + 0 x 2^3 + 1 x 2^2 + 1 x 2^1 + 1 x 2^0
    

    Вот что я вам уже показал:

    0 + 64 + 0 + 0 + 0 + 4 + 2 + 1
    = 64 + 4 + 2 + 1
    = 71
    

Кроме того, возможно, вам было интересно, что означают 0x41 и 0x61. Часть 0x указывает, что следующие цифры следует понимать как шестнадцатеричные, которые являются базовыми 16. В нашей числовой системе всего 10 цифр, поэтому нам нужно еще 6 цифр. Таким образом, шестнадцатеричное число использует цифры 0-9 и обрабатывает буквы AF как оставшиеся цифры, где A - от 10 до F как 15. Шестнадцатеричное очень удобно для компьютеров, потому что 16 - это мощность 2 и 8-разрядный байт, таким образом занимает ровно две шестнадцатеричные цифры для кодирования (и каждая шестнадцатеричная цифра кодирует ровно четыре двоичных разряда). Принимая 0x41, расширяя 4 до его двоичного представления 0100 и расширяя 1 до его двоичного представления 0001, вы получаете 01000001, который вы можете увидеть как код для A, как показано. Чтобы преобразовать его в десятичный, это 4 x 16 + 1 x 1 = 65. Мы умножаем число 4 на 16, потому что каждая последующая шестнадцатеричная цифра влево равна 16 раз предыдущей цифре, следуя той же схеме, что и я показал выше для базовых 2 и 10.

Надеюсь, этого достаточно, чтобы вы поняли немного больше о двоичных и ASCII-кодах.

Примечание 1: причина для 8 бит в байте вместо 2, как вы могли бы подумать, это то, что в первые дни вычислений было принято решение, что 8 - гораздо более полезное количество бит, как 2-битное "byte" будет кодировать только 4 значения. Для передачи букв верхнего и нижнего регистра только одного алфавита потребуется 3 байта! В двоичном коде нет ничего, что заставляет выбирать 8 бит на байт, за исключением того, что 8 также является степенью 2, что делает большую часть математики более простой в работе с бинарной информацией, а вещи лучше выравниваются по краям. Если бы они выбрали 6 бит на байт, я уверен, что все получилось бы неловко и не использовало бы весь диапазон доступных значений.

Примечание 2: Моя система из пяти бит в 10 байт основана на нецелесообразности использования десяти 10 бит на байт, что дает действительно огромное количество, которое будет тратить много места на хранение. Я выбрал пять, потому что десять равномерно делится им, что, несомненно, было бы полезно. (Первоначально мой ответ использовал десять 10 бит на 10 байт, но он был слишком проклят большим!)

Ответ 2

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

Ответ 3

взгляните, 6-й бит = 32, поэтому, если вы перевернете его, вы отложите или добавьте 32

Bit value
1   1
2   2
3   4
4   8
5   16
6   32 (32 = hex 20)

Теперь, если вы посмотрите здесь http://asciitable.com/, вы можете увидеть таблицу ascii для всех символов и заметите, что A = 65 и a = 97

Ответ 4

http://asciitable.com/

0x61 is hexadecimal for 97 = a
0x41 is hexadecimal for 65 = A

Таким образом, вычитание/добавление десятичного числа 32 действительно является способом преобразования в верхний регистр или нижний регистр.

Z is 90 = 0b1111010    = 0x5A
z is 122 = 0b1011010   = 0x7A

Какая разница в 0b01000000 в двоичном формате или 0x20 или 32 в десятичной форме.

Таким образом, происходит переход на 6-й бит.

Ответ 5

Чтобы добавить или вычесть 32, вы сначала должны знать, больше ли символ больше или меньше "A".

Когда эта книга была написана, языки программирования, используемые большинством людей, не имели строк, или .equalsIgnoreCase. Это было pre-i18n, и когда у бизнеса был сервер, вы бы подключили к нему telnet (например, xterm) и получили меню командной строки. То, что он описывал, обычно использовалось для создания приятного без учета регистра меню для ваших пользователей, используя численное расположение таблицы ascii.

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

c = c | 32//в верхний регистр

c = c и (1 + 2 + 4 + 8 + 16 + 0 + 64 + 128)//в нижнем регистре

Скажем, у вас был Java-подобный язык, без объектов или стандартных библиотек. Ваш автор сети попросит вас ввести такой код:

    public static void main()
    {
        println("What would you like to do?");
        println("Inventory (inv)");
        println("Reports (rep)");

        char[] ca = readUserInput();        
        for (int i = 0; i < ca.length; i++)
            ca[i] = ca[i] | 32;  // convert to uppercase, by ensuring bit 32 is set

        if (compareInput(ca, "INV") == true)
            doInventory();
    }

Попробовали ли вы искать Google, а иногда и заглавили имя человека?

Ответ 6

Я думаю, что большинство этих ответов излишне сложны и иногда снисходят.

Отображение символа десятичного в ascii произвольно и на самом деле не имеет никакого отношения к пониманию того, как работает база 2 или база 10. Это чисто удобная вещь. Если кто-то ошибочно закодировал строчный символ, но имел в виду прописную букву, удобнее было просто перевернуть один бит вместо того, чтобы перекодировать весь байт. Он менее подвержен человеческой ошибке, чтобы просто щелкнуть один бит. Если выход "a", но мы хотели "A", по крайней мере, мы знаем, что мы получили большую часть бит, и нам просто нужно перевернуть 2 ^ 5, чтобы добавить или вычесть 32. Это так просто. Зачем выбирать конкретно бит 5 (это не 6, как говорили некоторые, вы начинаете с 0..), что ясно, что тот, который имеет смысл удовлетворять двум диапазонам в 26 символов, только с одним битом. Если вы сделали это на меньшем значении, вам придется перевернуть более одного.