web-dev-qa-db-ja.com

大文字と小文字の違いは1ビットだけですか?

Behrouza Forouzanが書いたData and Communication Networkingの本で、7ビットコードで1ビットだけ異なる大文字と小文字について1つの例を見つけました。

たとえば、文字Aは1000001(0x41)で、文字aは1100001(0x61)です。違いはビット6で、大文字は0、小文字は1です。 1つのケースのコードがわかっている場合は、32を10進数で加算または減算することで、他のケースのコードを簡単に見つけることができます。または、6番目のビットを反転するだけでもかまいません。

これはどういう意味ですか?

私はこれらすべてのものと非常に混乱していることに気づきました。誰かがこれらのことが実際にどのように機能するかの例を提供できますか?

14
Vibhakar SInha

より身近なケースを使用してみましょう:ベース10。

  1. 各10ビットが0〜9の値を格納し、10バイトが5 10ビット長である10基のコンピューターがあるとします。これにより、各バイトは100,000の値(0〜99,999)を格納できます。

  2. このコンピューターが他のコンピューターとテキストデータを通信できるように、10バイトの特定の位置に文字を割り当てたいとします。これを行う方法の1つは、次のようになります。

    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
    
  3. 右から3番目の列で、各小文字が大文字と10ビットの数字が1つだけ異なることを確認しましたか?このように設計することはhaveではありませんでした。文字の大文字と小文字を調整したいときはいつでも、数字の残りの部分を気にすることなく、または26の異なる変換に煩わされることなく、数字(10ビット)の1つを変更することができるので、 one。 2番目の桁を選択することはできませんでした。100桁離れているのではなく、10桁しか離れておらず、重複しているためです。

  4. これで、基数2ではまったく同じですが、各ビットが0〜9を表す代わりに、0〜1しか表すことができません。 2つのビットを8つ使用すると、可能な組み合わせは0〜255の256のみになります。バイナリの大文字と小文字の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ビットの桁が1つだけ異なります。ここでは、右から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.
    

    上記で構築した特殊な基本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.
    

    バイナリの「Val」行をもう一度見てください。右から見て、各値が前の値の2倍であることがわかりますか? 1、2、4、8、16、32、64、128、256、512などになるたびに2倍になります。これは、10進数の桁の位置が10のべき乗で値を決定するのと同じように、2桁の桁の位置がその値を決定する方法です:1、10、100、1000、10000、100000など。

    107を107に変換するだけだったので、これはばかげているように見えますが、107は単なる数値ではなく、以下の省略形です。

    1 hundreds + 0 tens + 7 ones.
    

    それを表すもう1つの方法は、

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

    同様に、01000111は単なる2進数ではなく、

    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進数である16進数として理解されることを示しています。数値システムには10桁しかないため、何らかの方法でさらに6桁必要です。したがって、16進数は0〜9の数字を使用し、文字AFを残りの数字として扱います。Aは10からFまでの15として扱います。16は2の累乗であり、8ビットバイトなので、16進数はコンピューターにとって非常に便利です。エンコードするのに正確に2桁の16進数を使用します(各16進数は4桁の2進数をエンコードします)。 0x41、 拡大する 4からそのバイナリ表現0100および展開1からそのバイナリ表現0001取得します01000001は、表示されているAのコードです。これを10進数に変換すると、4 x 16 + 1 x 1 = 65になります。4を16で乗算します。これは、左に続く各16進数字が前の数字の16倍であるため、上で示した2と10と同じパターンに従います。

これで、バイナリとASCIIコードについての理解が深まると思います。

注1:ご想像のとおり、バイトが2ビットではなく8ビットである理由は、コンピューティングの初期の頃には、8の方がはるかに有用なビット数であることが判明したためです。 2ビットの「バイト」は4つの値のみをエンコードします。アルファベットの大文字と小文字だけを送信するには、3バイト必要です! 8は2の累乗であり、バイナリ情報の処理に関連する多くの計算がより簡単になり、物事がエッジ上でより適切に整列することを除いて、バイトあたり8ビットの選択を強制するバイナリに固有のものはありません。彼らが1バイトあたり6ビットを選択した場合、問題はうまくいかず、利用可能なすべての値の範囲をうまく利用できなかったと私は確信しています。

注2: 10バイトに5ビットを使用する私のシステムは、1バイトあたり10ビットを使用することの非実用性に基づいています。 5を選択した理由は、10がそれで割り切れるので、間違いなく役立つからです。 (元々、私の回答は10バイトあたり10ビットを使用していましたが、それは大きすぎます!)

35
ErikE

大文字と小文字のこの関係は慎重に行われました。 ASCII=コードが定式化されたとき、コンピュータのハードウェアは原始的であり、ソフトウェアはすべてのバイトを節約する必要がありました。単一ビットの反転は、達成するためにハードウェアまたはコードをほとんど必要としません。

3
Mark Ransom

32を加算または減算するには、まず文字が「A」より大きいか小さいかを知る必要があります。

この本が書かれたとき、ほとんどの人が使用していたプログラミング言語には、文字列や.equalsIgnoreCaseがありませんでした。これはi18nより前のバージョンでした。企業にサーバーがあった場合、(xtermのように)Telnetで接続し、コマンドラインメニューを取得します。彼が説明していることは、ASCIIテーブルの数値レイアウトを利用して、ユーザーにニースの大文字と小文字を区別しないメニューを作成するために通常使用されました。

文字がすでに大文字であるか小文字であるかに関係なく、いずれかの方向で計算を行うビット単位のアセンブラー命令があるため、非常に高速になる可能性があります。

c = c | 32 //大文字に

c = c&(1 + 2 + 4 + 8 + 16 + + 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を検索してみて、人の名前を大文字にすることはありますか?

2
Brian Maltzan

http://asciitable.com/

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

したがって、10進数の32の減算/加算は、実際に大文字/小文字に変換する方法です。

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

これは、バイナリでは0b01000000、10進数では0x20または32の違いです。

したがって、6番目のビットを切り替えるとケースが変わります。

1
Gazler

これらの回答のほとんどは、不必要に複雑で、たまに見下されていると思います。

10進数からASCII文字へのマッピングは任意であり、基数2または基数10がどのように機能するかを理解することとは何の関係もありません。それは純粋に便利なものです。誰かが誤って小文字をコーディングしたが大文字を意味する場合、バイト全体を再コーディングする必要がなく、1ビットだけフリップする方が便利です。 1ビットをフリップするだけの方が、人為的エラーが発生しにくくなります。出力が「a」であるが「A」が必要な場合、少なくともほとんどの部分が正しいことがわかっているので、2 ^ 5を反転させて32を加算または減算するだけです。これは簡単です。なぜ具体的にビット5を選択するのか(一部の人が言ったように6ではない、0から開始する)。1つのビットフリップで26文字の2つの範囲を満たすのに意味があるのは明らかです。値の小さいビットでこれを行った場合は、1つ以上フリップする必要があります。

1
shake

見てみましょう、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であることがわかります。

1
SQLMenace
template<char TLBound, char TUBound>
struct CharRange
{
    enum 
    {
        LBound = TLBound,
        UBound = TUBound
    };

    static bool InRange(char ch)
    {
        return (ch >= LBound)  && (ch <= UBound);
    };
};

typedef CharRange<'a', 'z'> lcaseLetters;
typedef CharRange<'A', 'Z'> ucaseLetters;

char toUpper(char ch)
{
    if(lcaseLetters::InRange(ch))
    {
        return (ch ^ (0x1 << 5));
    }

    return ch;
}

char toLower(char ch)
{
    if(ucaseLetters::InRange(ch))
    {
        return (ch ^ (0x1 << 5));
    }

    return ch;
}
0
Nitheesh George