ハミングコード

2進ハミング符号
ハミング(7,4)コード(r = 3
名前の由来リチャード・W・ハミング
分類
タイプ線形ブロックコード
ブロック長2 r − 1ただしr ≥ 2
メッセージの長さ2 rr − 1
レート1 − r/(2 r − 1)
距離3
アルファベットのサイズ2
表記[2 r − 1, 2 rr − 1, 3] 2コード
プロパティ
完璧なコード

コンピュータサイエンス電気通信において、ハミング符号は線形誤り訂正符号の一種である。ハミング符号は1ビットと2ビットの誤りを検出したり、未訂正の誤りを検出せずに1ビットの誤りを訂正したりすることができる。対照的に、単純なパリティ符号は誤りを訂正できず、奇数ビットの誤りしか検出できない。ハミング符号は完全符号であり、ブロック長最小距離が3である符号で可能な限り最高のレートを実現する。[ 1 ]リチャード・W・ハミングは1950年に、パンチカードリーダーによってもたらされる誤りを自動的に訂正する方法としてハミング符号を発明した。最初の論文では、ハミングは一般的なアイデアを詳しく説明したが、特に4ビットのデータに3つのパリティビットを追加するハミング(7,4)符号に焦点を当てていた。[ 2 ]

数学的に言えば、ハミング符号はバイナリ線形符号の一種です。r ≥ 2の各整数に対して、ブロック長n = 2 r − 1メッセージ長k = 2 rr − 1の符号語が存在します。したがって、ハミング符号のレートはR = k / n = 1 − r / (2 r − 1)となり、これは最小距離が 3 (つまり、任意の符号語から他の任意の符号語に移行するために必要なビット変更の最小数は 3) でブロック長が2 r − 1である符号で可能な最大値です。ハミング符号のパリティ チェック マトリックスは、長さrの非ゼロの列をすべてリストすることによって構築されます。つまり、ハミング符号のデュアル コードは短縮アダマール コード (シンプレックス コードとも呼ばれる) になります。パリティ チェック マトリックスには、任意の 2 つの列が互いに線形独立であるという特性があります。

ハミング符号がデータに追加する冗長性には限界があるため、エラー率が低い場合にのみエラーを検出して訂正できます。これは、ビットエラーが極めて稀なコンピュータメモリ(通常は RAM)の場合に当てはまり、ハミング符号が広く使用されています。この訂正システムを備えたメモリは、 ECC メモリと呼ばれます。このコンテキストでは、1 つの余分なパリティ ビットを持つ拡張ハミング符号がよく使用されます。拡張ハミング符号はハミング距離 4 を実現します。これにより、デコーダーは、最大で 1 ビット エラーが 1 つ発生した場合と、2 ビット エラーが発生した場合を区別できます。この意味で、拡張ハミング符号は、単一エラー訂正および二重エラー検出であり、SECDEDと略されます。

歴史

ハミング符号の発明者であるリチャード・ハミングは、1940年代後半にベル研究所でベルモデルVコンピュータの開発に携わっていました。これは、サイクルタイムが数秒単位の電気機械式リレー式マシンです。入力は、幅7/8インチで、1列あたり最大6つの穴が開いたパンチ紙テープに入力されました。平日は、リレーのエラーが検出されると、マシンは停止してライトを点滅させ、オペレーターが問題を修正できるようにしました。営業時間外や週末など、オペレーターがいない時間帯には、マシンは次のジョブへと移行しました。

ハミングは週末も作業を続け、検出されたエラーのためにプログラムを最初からやり直さなければならないことに苛立ちを募らせていた。録音されたインタビューの中で、ハミングは「それで私はこう言った。『ちくしょう、機械がエラーを検出できるのなら、なぜエラーの位置を特定して修正できないんだ?』」と述べている。[ 3 ]その後数年間、彼はエラー訂正の問題に取り組み、ますます強力なアルゴリズムを次々と開発していった。1950年には、現在ではハミング符号として知られるコードを発表し、これはECCメモリなどのアプリケーションで現在も使用されている。

ハミング以前のコード

ハミング コード以前にもいくつかの単純なエラー検出コードが使用されていましたが、同じスペースのオーバーヘッドでハミング コードほど効果的なものはありませんでした。

パリティ

パリティは、前のデータに含まれる 1 の個数(値が 1 であるビット位置)が偶数奇数かを示す1ビットを追加します。送信中に奇数ビットが変更された場合、メッセージのパリティが変更され、この時点でエラーが検出されます。ただし、変更されたビットはパリティビット自体である可能性があります。最も一般的な規則では、パリティ値が 1 の場合はデータに含まれる 1 の個数が奇数であることを示し、パリティ値が 0 の場合は 1 の個数が偶数であることを示します。変更されたビットの数が偶数の場合、チェックビットは有効となり、エラーは検出されません。

さらに、パリティは、たとえエラーを検出できたとしても、どのビットにエラーが含まれていたかを示すことができません。データを完全に破棄し、最初から再送信する必要があります。ノイズの多い伝送媒体では、正常な伝送に長い時間がかかったり、そもそも伝送されない可能性もあります。パリティチェックは1ビットしか使用しないため品質は低いものの、この方法はオーバーヘッドが最も少なくなります。

5つのうち2つのコード

2 out of five コードは、正確に3つの0と2つの1からなる5ビットを使用する符号化方式です。これにより、0~9の数字を表現するのに十分な組み合わせが実現されます。この方式は、すべての単一ビットエラー、すべての奇数ビットエラー、そして一部の偶数ビットエラー(例えば、両方の1ビットが反転している場合)を検出できます。ただし、これらのエラーを訂正することはできません。 5310{\displaystyle {\binom {5}{3}}=10}

繰り返し

当時使用されていた別のコードでは、データ ビットがすべてのデータ ビットを複数回繰り返して、正しく送信されたことを確認するものでした。たとえば、送信するデータ ビットが 1 の場合、n = 3 の繰り返しコードでは 111 が送信されます。受信した 3 つのビットが同一でない場合は、送信中にエラーが発生したことになります。チャネルが十分にクリーンであれば、ほとんどの場合、3 つの繰り返しごとに 1 ビットだけが変化します。したがって、001、010、100 はそれぞれ 0 ビットに対応し、110、101、011 は 1 ビットに対応して、同じ桁 (「0」または「1」) の数が多い方が、データ ビットが何であるかを示します。エラーがあっても元のメッセージを再構築できるこの機能を備えたコードは、エラー訂正コードと呼ばれます。この 3 つの繰り返しコードは、パリティ ビットが 2 ビットあり、データ ビット が2 2 − 2 − 1 = 1であるため、 m = 2のハミング コードです。

しかし、このようなコードではすべてのエラーを正しく修復することはできません。例えば、チャネルが2ビット反転し、受信機が001を受け取った場合、システムはエラーを検出しますが、元のビットが0であると判断するため、これは誤りです。ビット列のサイズを4に増やすと、2ビットエラーはすべて検出できますが、訂正することはできません(パリティビットの数が偶数であるため)。5ビットにすると、2ビットエラーはすべて検出・訂正できますが、3ビットエラーはすべて検出・訂正できません。

さらに、パリティ ビット文字列のサイズを増やすことは非効率的であり、元のケースではスループットが 3 倍減少し、より多くのエラーを検出して修正するために各ビットの複製回数が増えると効率が大幅に低下します。

説明

メッセージにさらに多くのエラー訂正ビットが含まれ、それらのビットを、異なる不正なビットが異なるエラー結果を生成するように配置できれば、不正なビットを識別できるようになります。7ビットのメッセージでは、単一ビットエラーが7つ発生する可能性があるため、3つのエラー制御ビットがあれば、エラーが発生したことだけでなく、どのビットがエラーの原因となったかを特定できる可能性があります。

ハミングは、2/5を含む既存の符号化方式を研究し、その概念を一般化しました。まず、ブロック内のデータビット数と誤り訂正ビット数を含む、システムを記述するための命名法を開発しました。例えば、パリティはデータワードごとに1ビットを含むため、 ASCIIワードが7ビットであると仮定すると、ハミングはこれを(8,7)符号と表現しました。これは合計8ビットで、そのうち7ビットはデータです。繰り返しの例は、同じ論理に従って(3,1)となります。符号化率は、 2番目の数値を1番目の数値で割った値で、この繰り返しの例では1/3となります。

ハミングは2ビット以上の反転に伴う問題にも気づき、これを「距離」と表現しました(現在では彼の名にちなんでハミング距離と呼ばれています)。パリティの距離は2なので、1ビットの反転は検出できますが訂正できず、2ビットの反転は目に見えません。(3,1)繰り返しは距離が3です。これは、目に見えるエラーのない別のコードワードを得るために、同じ3ビットのビットを反転する必要があるためです。1ビットのエラーを訂正することも、2ビットのエラーを検出することもできますが、訂正することはできません。(4,1)繰り返し(各ビットが4回繰り返される)は距離が4なので、3ビットの反転は検出できますが訂正できません。同じグループで3ビットが反転した場合、訂正しようとすると誤ったコードワードが生成される可能性があります。一般的に、距離kのコードはk − 1個のエラー を検出できますが、訂正することはできません。

ハミングは、距離を可能な限り長くすることと、同時に符号化率を可能な限り高くすることという、2つの問題に同時に関心を抱いていました。1940年代に彼は、既存の符号を劇的に改善するいくつかの符号化方式を開発しました。彼のシステムの鍵は、パリティビットを重ね合わせることで、データだけでなく互いのチェックも可能にすることでした。

一般的なアルゴリズム

以下の一般的なアルゴリズムは、任意のビット数に対して単一誤り訂正(SEC)コードを生成します。基本的な考え方は、インデックスXOR( 1を含むすべてのビット位置のXOR)が0になるように誤り訂正ビットを選択することです。誤り訂正ビットとして、1、10、100など(バイナリ)の位置を使用します。これにより、メッセージ全体のインデックスXORが0になるように誤り訂正ビットを設定できることが保証されます。受信側がインデックスXORが0の文字列を受信した場合、破損はなかったと結論付けることができます。そうでない場合、インデックスXORは破損したビットのインデックスを示します。

次の説明からアルゴリズムを推測できます。

  1. ビットに 1 から番号を付けます (ビット 1、2、3、4、5、6、7、など)。
  2. ビット番号を 2 進数で書きます: 1、10、11、100、101、110、111、など。
  3. 2の累乗であるビット位置(その位置の2進形式で1ビットが1つある)はすべてパリティビットです:1、2、4、8など(1、10、100、1000)
  4. その他のすべてのビット位置は、その位置のバイナリ形式で 2 つ以上の 1 ビットを持つ場合、データ ビットです。
  5. 各データ ビットは、そのビット位置のバイナリ形式によって決定される 2 つ以上のパリティ ビットの一意のセットに含まれます。
    1. パリティ ビット 1 は、最下位ビットが設定されているすべてのビット位置をカバーします: ビット 1 (パリティ ビット自体)、3、5、7、9 など。
    2. パリティ ビット 2 は、2 番目に重要なビットが設定されているすべてのビット位置 (ビット 2 ~ 3、ビット 6 ~ 7、ビット 10 ~ 11 など)をカバーします。
    3. パリティ ビット 4 は、最下位から3 番目のビットが設定されているすべてのビット位置 (ビット 4 ~ 7、ビット 12 ~ 15、ビット 20 ~ 23 など)をカバーします。
    4. パリティ ビット 8 は、最下位から4 番目のビットが設定されているすべてのビット位置 (ビット 8 ~ 15、ビット 24 ~ 31、ビット 40 ~ 47 など)をカバーします。
    5. 一般に、各パリティ ビットは、パリティ位置とビット位置のビット単位の AND がゼロ以外となるすべてのビットをカバーします。

エンコードされるデータのバイトが 10011010 の場合、データ ワード (パリティ ビットを表すために _ を使用) は __1_001_1010 になり、コード ワードは 011100101010 になります。

パリティの選択(偶数または奇数)は無関係ですが、エンコードとデコードの両方で同じ選択を使用する必要があります。

この一般的なルールは視覚的に表すことができます。

ビット位置1234567891011121314151617181920...
エンコードされたデータビット 1ページ目 2ページ目d1 4ページ目d2d3d4 8ページd5d6d7d8d9d10d11 16ページd12d13d14d15
パリティビットカバレッジ 1ページ目 はいはいはいはいはいはいはいはいはいはい
2ページ目 はいはいはいはいはいはいはいはいはいはい
4ページ目 はいはいはいはいはいはいはいはいはい
8ページ はいはいはいはいはいはいはいはい
16ページ はいはいはいはいはい

ここに示されているのは、エンコードされた 20 ビット (パリティ 5 ビット、データ 15 ビット) だけですが、パターンは無限に続きます。目視で確認できるハミング符号の重要な点は、任意のビットが一意のパリティ ビット セットに含まれていることです。エラーをチェックするには、すべてのパリティ ビットをチェックします。エラー シンドロームと呼ばれるエラー パターンにより、エラーのあるビットが識別されます。すべてのパリティ ビットが正しければ、エラーはありません。そうでない場合は、エラーのあるパリティ ビットの位置の合計により、エラーのあるビットが識別されます。たとえば、位置 1、2、8 のパリティ ビットがエラーを示している場合、ビット 1+2+8=11 にエラーがあります。1 つのパリティ ビットだけがエラーを示している場合、そのパリティ ビット自体にエラーがあります。

mビットのパリティビットで、1から10までのビットをカバーできます。パリティビットを除いた残りのビットはデータとして使用できます。m変化すると、考えられるすべてのハミング符号が得られます。 2メートル1{\displaystyle 2^{m}-1}2メートルメートル1{\displaystyle 2^{m}-m-1}

パリティビット合計ビット数データビット名前レート
231ハミング(3,1) (三重繰り返し符号1/3 ≈ 0.333
374ハミング(7,4)4/7 ≈ 0.571
41511ハミング(15,11)11/15 ≈ 0.733
53126ハミング(31,26)26/31 ≈ 0.839
66357ハミング(63,57)57/63 ≈ 0.905
7127120ハミング(127,120)120/127 ≒ 0.945
8255247ハミング(255,247)247/255 ≈ 0.969
9511502ハミング(511,502)502/511 ≈ 0.982
...
メートルn2メートル1{\displaystyle n=2^{m}-1}2メートルメートル1{\displaystyle k=2^{m}-m-1}ハミング2メートル12メートルメートル1{\displaystyle (2^{m}-1,2^{m}-m-1)}2メートルメートル1/2メートル1{\displaystyle (2^{m}-m-1)/(2^{m}-1)}

追加パリティ付きハミング符号(SECDED)

ハミング符号の最小距離は3です。これは、デコーダーが単一のエラーを検出して訂正できることを意味しますが、あるコードワードの2ビットエラーと別のコードワードの1ビットエラーを区別することはできません。そのため、訂正を試みない限り、一部の2ビットエラーは1ビットエラーであるかのように誤ってデコードされ、検出されないことがあります。

この欠点を補うために、ハミング符号はパリティビットを追加することで拡張できます。これにより、ハミング符号の最小距離を4に増やすことができ、デコーダは1ビットエラーと2ビットエラーを区別できるようになります。つまり、デコーダは1ビットエラーを検出・訂正すると同時に、2ビットエラーも検出(訂正はできません)できます。デコーダがエラー訂正を試みない場合、3ビットエラーを確実に検出できます。一方、デコーダがエラー訂正を行う場合、一部の3ビットエラーは1ビットエラーと誤認され、誤った値に「訂正」されます。したがって、エラー訂正は確実性(3ビットエラーを確実に検出する能力)と回復力(1ビットエラーが発生しても動作を継続する能力)の間のトレードオフとなります。

kデータ ビットの場合、SECDED 方式では次のものが必要です。

  • nをkより大きい 2 のべき乗とします。
  • lをfloor(log 2 ( k ))、hをl + 1とします。
  • kn - l - 1の場合、必要な追加ビット数はlです。それ以外の場合、必要なカウント数はhです。

この拡張ハミング符号は、 1961年のIBM 7030 Stretchに始まり、コンピュータメモリシステムで普及しました。[ 4 ]そこではSECDED (またはSEC-DED、 Single Error Correction、Double Error Detectionの略)と呼ばれています。[ 5 ]メモリシステムの一般的な形式には、(39,32)と(72,64)があります。(2 m - 1の形式のコードワード長を使用する方が効率的ですが、既存のコンピュータデータワードサイズが2の累乗であるため、この選択はできません。ただし、通信システムとデータストレージシステムはこれを活用します。)21世紀のサーバーコンピュータは、一般的にSECDEDレベルの保護を維持していますが、ハミング法は使用しなくなり、代わりにより長いコードワード(128~256ビットのデータ)と修正されたバランスパリティチェックツリーを備えた設計に依存しています。[ 4 ](72,64)ハミング符号は、ザイリンクスFPGAファミリーを含む一部のハードウェア設計で依然として普及しています。[ 4 ]

[7,4] ハミング符号

4つのデータビットと3つのパリティビット、およびどのパリティビットがどのデータビットに適用されるかをグラフィカルに表現します。

1950年、ハミングは[7,4]ハミング符号を導入しました。この符号は、4ビットのデータビットに3ビットのパリティビットを付加することで7ビットに符号化します。前述の通り、この符号は1ビットの誤りを検出・訂正することも、1ビットと2ビットの両方の誤りを検出・訂正することもできます(ただし訂正はできません)。

全体のパリティビットを追加すると、[8,4]拡張ハミングコードになり、シングルビットエラーの検出と修正、およびダブルビットエラーの検出(修正は不可)が可能になります。

GとHの構築

この行列 は線形( nk)コード の(標準)生成行列と呼ばれる。G:=T{\displaystyle \mathbf {G} :={\begin{pmatrix}{\begin{array}{c|c}I_{k}&-A^{\text{T}}\\\end{array}}\end{pmatrix}}}

これはパリティ検査行列と呼ばれます。 H:=n{\displaystyle \mathbf {H} :={\begin{pmatrix}{\begin{array}{c|c}A&I_{nk}\\\end{array}}\end{pmatrix}}}

これはGHを標準形式(または体系的形式)で構築したものである。形式に関わらず、線形ブロック符号の GHは以下を満たす必要がある。

HGT0{\displaystyle \mathbf {H} \,\mathbf {G} ^{\text{T}}=\mathbf {0} }、すべてゼロの行列。[ 6 ]

[7, 4, 3] = [ nkd ] = [2 m  − 1, 2 m  − 1 −  m , 3] なので、ハミング符号のパリティ検査行列Hは、長さmの列のうち互いに独立な 列をすべて列挙することによって構築されます。

したがって、Hは、左辺がn個の非零組のすべてである行列であり、行列の列におけるn個の組の順序は関係ありません。右辺は ( n  −  k )単位行列です。

したがって、Hの左側の転置を G の左側の単位 k - 単位行列と取ること、  HからG取得できます。

コード生成行列パリティチェック行列は次のとおりです。 G{\displaystyle \mathbf {G} }H{\displaystyle \mathbf {H} }

G:=100011001001010010011000111147{\displaystyle \mathbf {G} :={\begin{pmatrix}1&0&0&0&1&1&0\\0&1&0&0&1&0&1\\0&0&1&0&0&1&1\\0&0&0&1&1&1&1\end{pmatrix}}_{4,7}}

そして

H:=11011001011010011100137{\displaystyle \mathbf {H} :={\begin{pmatrix}1&1&0&1&1&0&0\\1&0&1&1&0&0&1&0\\0&1&1&1&0&0&1\end{pmatrix}}_{3,7}.}

最後に、これらの行列は以下の操作によって同等の非体系的コードに変換することができる。[ 6 ]

  • 列の順列(列の交換)
  • 基本的な行演算(行を行の線形結合に置き換える)

エンコーディング

上記の行列から、2 k = 2 4 = 16 個のコードワードが得られます。バイナリデータビットの行ベクトルを とします。16個のデータベクトルのいずれのコードワードも、標準的な行列積で与えられます。この積は 2 を法として計算されます。 1つの{\displaystyle {\vec {a}}}1つの[1つの11つの21つの31つの4]1つの{01}{\displaystyle {\vec {a}}=[a_{1},a_{2},a_{3},a_{4}],\quad a_{i}\in \{0,1\}}×{\displaystyle {\vec {x}}}1つの{\displaystyle {\vec {a}}}×1つのG{\displaystyle {\vec {x}}={\vec {a}}G}

例えば、 とします。上記の生成行列を使用すると、(和に 2 を法として適用した後) 1つの[1011]{\displaystyle {\vec {a}}=[1,0,1,1]}G{\displaystyle G}

×1つのG1011100011001001010010011000111110112321011010{\displaystyle {\vec {x}}={\vec {a}}G={\begin{pmatrix}1&0&1&1\end{pmatrix}}{\begin{pmatrix}1&0&0&1&1&0\\0&1&0&0&1&0&1\\0&0&1&0&1&1&1\\0&0&0&1&1&1&1\\\end{pmatrix}}={\begin{pmatrix}1&0&1&1&2&3&2\end{pmatrix}}={\begin{pmatrix}1&0&1&1&0&1&0\end{pmatrix}}}

[8,4] パリティビットを追加したハミング符号

上記と同じ[7,4]の例ですが、パリティビットが追加されています。この図は、この例の行列Hに対応するものではありません。

[7,4]ハミング符号は、(7,4)符号化ワードにパリティビットを追加することで簡単に[8,4]符号に拡張できます(Hamming(7,4)を参照)。これは、修正された行列でまとめることができます。

G:=1110000110011001010101011101001048{\displaystyle \mathbf {G} :={\begin{pmatrix}1&1&1&0&0&0&0&1\\1&0&0&1&1&0&0&1\\0&1&0&1&0&1&0&1\\1&1&0&1&0&0&1&0\end{pmatrix}}_{4,8}}

そして

H:=(10101010011001100001111011111111)4,8.{\displaystyle \mathbf {H} :={\begin{pmatrix}1&0&1&0&1&0&1&0\\0&1&1&0&0&1&1&0\\0&0&0&1&1&1&1&0\\1&1&1&1&1&1&1&1\end{pmatrix}}_{4,8}.}

Hは標準形ではないことに注意してください。Gを得るには、基本的な行演算を用いてHと等価な体系的な形の行列を得ることができます。

H=(01111000101101001101001011100001)4,8.{\displaystyle \mathbf {H} =\left({\begin{array}{cccc|cccc}0&1&1&1&1&0&0&0\\1&0&1&1&0&1&0&0\\1&1&0&1&0&0&1&0\\1&1&1&0&0&0&0&1\end{array}}\right)_{4,8}.}

例えば、この行列の1行目は、Hの2行目と3行目の非体系的な和である。上述のハミング符号の体系的な構成を用いると、行列Aは明らかであり、Gの体系的な形は次のように書ける。

G=(10000111010010110010110100011110)4,8.{\displaystyle \mathbf {G} =\left({\begin{array}{cccc|cccc}1&0&0&0&0&1&1&1\\0&1&0&0&1&0&1&1\\0&0&1&0&1&1&0&1\\0&0&0&1&1&1&1&0\end{array}}\right)_{4,8}.}

G の非体系的形式は、この行列と一致するように行削減 (基本的な行演算を使用) できます。

4 行目を追加すると、すべてのコードワード ビット (データとパリティ) の合計が 4 番目のパリティ ビットとして計算されます。

例えば、1011は(このセクションの冒頭で示したGの非体系的形式を用いて)01 1 0 011 0と符号化されます。ここで、青い数字はデータ、赤い数字は[7,4]ハミング符号のパリティビット、緑の数字は[8,4]符号によって追加されたパリティビットです。緑の数字は[7,4]符号語のパリティを偶数にします。

最後に、最小距離が[7,4]コードでは3であったのに対し、[8,4]コードでは4に増加していることがわかります。したがって、このコードは[8,4]ハミングコードとして定義できます。

[8,4]ハミング符号をデコードするには、まずパリティビットをチェックします。パリティビットがエラーを示している場合、単一のエラー訂正([7,4]ハミング符号)はエラー位置を示し、「エラーなし」はパリティビットを示します。パリティビットが正しい場合、単一のエラー訂正は2つのエラー位置の(ビット単位の)排他的論理和を示します。位置が等しい場合(「エラーなし」)、ダブルビットエラーは発生していないか、または相殺されています。それ以外の場合は、ダブルビットエラーが発生しています。

参照

注記

  1. ^補題12を参照
  2. ^ハミング(1950)、153-154頁。
  3. ^トンプソン、トーマス・M.(1983)、誤り訂正符号から球面パッキングを経て単純群へ、カーラス数学モノグラフ(#21)、アメリカ数学協会、pp.  16-17ISBN 0-88385-023-0
  4. ^ a b c Kythe & Kythe 2012、p. 115。
  5. ^ Kythe & Kythe 2012、95ページ。
  6. ^ a bムーンT. 誤り訂正符号化:数学的手法とアルゴリズム. ジョン・ワイリー・アンド・サンズ, 2005.(第3巻) ISBN 978-0-471-64800-0

参考文献