大写和小写字母如何仅相差一位?

Vib*_*nha 13 ascii bit-manipulation case-sensitive

我在Behrouza Forouzan撰写的数据和通信网络书中找到了一个关于大写和小写字母的例子,它们在7位代码中只有一位不同.

例如,字符A是1000001(0x41),字符a是1100001(0x61).区别在第6位,大写字母为0,小写字母为1.如果我们知道一种情况的代码,我们可以通过在十进制中加上或减去32来轻松找到另一种情况的代码,或者我们可以只翻转第六位.

这是什么意思呢?

我发现自己对所有这些事情都非常困惑.有人可以举例说明这些事情是如何运作的吗?

Eri*_*ikE 35

让我们使用一个你会发现更熟悉的案例:基础10.

  1. 假设我们有一个基本10计算机,其中每个10位存储0到9的值,10byte是5 10位长,因此每个字节可以存储100,000个值(0到99,999).

  2. 您希望将字母分配给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
    
    Run Code Online (Sandbox Code Playgroud)
  3. 你是否看到每个小写字母与大写字母只有一个10位数字,在右边的第3列中?它没有必须要这样设计的.它简单方便,因为任何时候我们想要调整一个字母的情况我们可以简单地修改其中一个数字(10位)而不关心数字的其余部分是什么,或者当我们可以做26个不同的转换时烦恼一个.我们不能选择第二个数字,因为它们不是相隔100个,而是相距10个并且会重叠.

  4. 现在,在基数2中它完全相同,但代替0-9的每个位,它只能代表0-1.使用8个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
    
    Run Code Online (Sandbox Code Playgroud)

    与以前一样,它们只有一个2位数字,在右边的第6列中.我们不能使用任何更靠右边的数字(更小)因为那时列表会重叠(2 ^ 5 = 32,因此我们使用了所有位0到5,但是2 ^ 4 = 16,这无法覆盖26个字母的字母).

  5. 只是为了填补一点,这里是这些二进制值意味着什么的一个例子.让我们拿一个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.
    
    Run Code Online (Sandbox Code Playgroud)

    在我上面构建的特殊基础10系统中对字母G执行相同的操作:

      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.
    
    Run Code Online (Sandbox Code Playgroud)

    回顾二进制的"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.
    
    Run Code Online (Sandbox Code Playgroud)

    我们可以代表的另一种方式是

    0 x 10^4 + 0 x 10^3 + 1 x 10^2 + 0 x 10^1 + 7 x 10^0.
    
    Run Code Online (Sandbox Code Playgroud)

    同样,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
    
    Run Code Online (Sandbox Code Playgroud)

    这是我已经向您展示的内容:

    0 + 64 + 0 + 0 + 0 + 4 + 2 + 1
    = 64 + 4 + 2 + 1
    = 71
    
    Run Code Online (Sandbox Code Playgroud)

此外,你可能一直在想什么0x410x61意味着什么.该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:你可能认为,一个字节而不是2位的8位的原因是在计算的早期阶段,确定8是一个更有用的位数,作为2位"字节"只会编码4个值.要传输字母表的大写和小写字母,需要3个字节!二进制中没有固有的东西强制每字节选择8位,除了8也是2的幂,这使得处理二进制信息的许多数学更简单,并且事物在边缘上更好地对齐.如果他们每个字节选择了6位,我相信事情会有尴尬的结果,并且不会充分利用可用的全部值.

注2:我的10字节中的5位系统是基于每字节使用10个10位的不切实际,这会产生非常大的数量,会浪费大量的存储空间.我选择了五个,因为十个可以被它整除,这无疑是有用的.(最初,我的答案是每10字节使用十个10比特,但它太大了!)

  • 01010111 01010100 01000110 00111111 (6认同)
  • 操作必须仍在阅读你的答案人,方式去. (2认同)

SQL*_*ace 1

看一下,第 6 位 = 32,所以如果你翻转它,你就会减去或加上 32

Bit value
1   1
2   2
3   4
4   8
5   16
6   32 (32 = hex 20)
Run Code Online (Sandbox Code Playgroud)

现在,如果您查看这里http://asciitable.com/,您可以看到所有字符的 ascii 表,并且会注意到 A = 65 和 a = 97

  • 更好的是,要转换为小写字母,请与值 32 执行按位“或”操作。要转换为大写字母,请与值 223 执行按位“与”操作。对于 CPU 来说,按位与和或的效率比加法和减法更高效。此外,位逻辑使您无需检查值(消除 IF 检查)。 (2认同)