半導体工学における数値計算の基礎

第1章 講義の概要と導入

1.1 講義の進め方と評価

本講義では、コンピュータを用いた解析やシミュレーションプログラムを理解し、開発するために必要な数値解析(Numerical Analysis)の基礎について解説します。私(担当教員)が前半の第1回から第7回までを担当し、コンピュータシミュレーションの基本と計算における誤差の発生源について説明します。

1.2 参考資料と教科書

数値解析や数値シミュレーションに関する英語の教科書は多数存在します。「Numerical Analysis」や「Numerical Simulation」といったキーワードで検索すると見つけることができます。日本語では「数値解析」で検索してください。

実用的なアルゴリズムやプログラミングに興味がある方には、『Numerical Recipes』シリーズを強くお勧めします。これは様々なプログラミング言語版が提供されており、非常に有名な教科書です。本講義でも適宜そのエッセンスを紹介します。

1.3 開発環境の推奨

プログラム開発には、Wordのようなワープロソフトは適していません。いわゆるテキストエディタを使用する必要があります。特定のテキストエディタをお持ちでない場合は、Microsoft Visual Studio Codeの使用を推奨します。

近年、生成AIの発展は目覚ましく、非常に有用なツールとなっています。AIを活用したチュートリアルビデオや講義スライドなども多数見つかりますので、参考にしてください(ただし、多くは日本語で提供されている可能性があります)。

1.4 本日の課題

本日出題される課題は、2日以内にLMS(Learning Management System)を通じて提出してください。提出期限は6月11日(水)の深夜23時59分です。LMSにアクセスできない場合は、メールで課題ファイルを送付してください。その際、ファイル名に学籍番号と氏名を含めるようお願いします。

本日の課題は以下の2問です。

  1. 基数変換:
  2. Pythonプログラムの解析:

第2章 コンピュータにおける数値表現の基礎

2.1 コンピュータの基本と2進数

コンピュータのCPUやメモリといったハードウェアは、基本的にバイナリ(2進数)論理回路で構成されています。これは、電気信号の「オン」と「オフ」、あるいは「高電圧」と「低電圧」といった2つの状態しか区別できないためです。したがって、コンピュータ内部における最も基本的な数値表現は2進数(Base 2)となります。

人間にとって2進数は扱いにくいため、通常は10進数(Base 10)16進数(Base 16)などが用いられますが、コンピュータ内部ではすべて2進数に変換されて処理されます。

2.2 基数変換の原理

ある基数(例えば10進数)で表現された数を、別の基数(例えば2進数)で表現し直すことを基数変換と呼びます。

2.2.1 R進数から10進数への変換

私たちが普段使う10進数は、例えば 1975 という数は以下のように表現されます。 1×103+9×102+7×101+5×1001 \times 10^{3} + 9 \times 10^{2} + 7 \times 10^{1} + 5 \times 10^{0} ここで「10」が基数(Base)です。

同様に、2進数で表現された数も、基数を「2」とすることで10進数に変換できます。例えば、2進数 11011 は以下のようになります。 1×24+1×23+0×22+1×21+1×20=16+8+0+2+1=271 \times 2^{4} + 1 \times 2^{3} + 0 \times 2^{2} + 1 \times 2^{1} + 1 \times 2^{0} = 16 + 8 + 0 + 2 + 1 = 27 したがって、2進数 11011 は10進数で 27 に対応します。

一般化された変換式: R進数で表現された数 (anan1a1a0)R(a_{n}a_{n - 1}\ldots a_{1}a_{0})_{R} は、10進数にすると以下のようになります。 (anan1a1a0)R=an×Rn+an1×Rn1++a1×R1+a0×R0(a_{n}a_{n - 1}\ldots a_{1}a_{0})_{R} = a_{n} \times R^{n} + a_{n - 1} \times R^{n - 1} + \ldots + a_{1} \times R^{1} + a_{0} \times R^{0}

2.2.2 10進数からR進数への変換

R進数から10進数への変換は上記の式で比較的容易ですが、その逆、つまり10進数からR進数への変換は少し複雑です。これは繰り返し除算の原理を用いて行います。

例として、10進数 374 を8進数(基数8)に変換する手順を見てみましょう。

  1. 3748 で割ります。 374 = 8 × 46 + 6 (余り 6) この余り 6 が8進数の最下位桁(右端)になります。

  2. 商の 46 を再び 8 で割ります。 46 = 8 × 5 + 6 (余り 6) この余り 6 が8進数の2桁目になります。

  3. 商の 5 を再び 8 で割ります。 5 = 8 × 0 + 5 (余り 5) この余り 5 が8進数の3桁目になります。商が 0 になったので計算は終了です。

結果として、余りを下から順に並べると 566 となります。 したがって、10進数 374 は8進数で 566 です。

2.3 8進数と16進数

2進数は桁数が多くなりがちで、人間が直接理解するには不便です。そのため、しばしば2進数をまとめて表現する8進数(Octal)16進数(Hexadecimal)が利用されます。

Base64エンコーディング: インターネット通信などで用いられるBase64エンコーディングは、64種類の文字(英数字、一部記号)を用いてバイナリデータをテキストデータに変換するものです。これは特定の基数変換とは少し異なりますが、バイナリデータを人間が扱える形式に変換するという点で関連性があります。

2.3.1 基数変換プログラムの利用

本日提供されるPythonプログラム base.py は、様々な基数間の変換をサポートしています。 例えば、16進数 fa を8進数に変換するには、コマンドプロンプトで以下のように実行します。 python base.py fa 16 8 このプログラムは、まず入力値を10進数に変換し、その後目標の基数に変換します。例えば fa (16進数) は 250 (10進数) に、そして 372 (8進数) に変換されることがわかります。


第3章 コンピュータにおけるデータ単位と数値型

3.1 データ単位: ビットとバイト

コンピュータ内部では、最も基本的なデータ単位はビット(bit)であり、これは2つの状態(0または1)を表します。しかし、多くのコンピュータシステムでは、8ビットをひとまとめにして扱います。この8ビットの塊をバイト(Byte)と呼びます。

3.2 数値型

コンピュータプログラムでは、様々な種類の数値を扱うために、数値型(Data Type)を使い分けます。主なものに整数型浮動小数点型があります。

3.2.1 整数型 (Integer Type)

整数型は小数点以下の値を持たない数(例: 1, 100, -5)を扱います。整数型は、割り当てられるビット長によって表現できる数値の範囲が異なります。また、負の数を扱うか否か(符号の有無)によっても分類されます。

3.2.2 浮動小数点型 (Floating-Point Type)

浮動小数点型は、小数点以下の値を持つ実数(例: 3.14, -0.001)を扱います。コンピュータでは、実数を「符号部」「指数部」「仮数部」に分けて表現します。


第4章 数値計算における誤差

4.1 浮動小数点数表現の限界と丸め誤差

実数には無限の桁数を持つものがありますが、コンピュータの浮動小数点型変数は有限のビット長しか持たないため、すべての実数を正確に表現することは不可能です。これにより生じる誤差を丸め誤差 (Rounding Error) と呼びます。

コンピュータ内部ではすべての数値が2進数で表現されます。浮動小数点数は一般的に ±1.F×2E\pm 1.F \times 2^{E} の形式で表現されます。

4.1.1 丸め誤差の累積

0.1 のような近似値を使って計算を繰り返すと、丸め誤差が累積し、最終結果に大きな影響を与えることがあります。 例えば、0.1 を100回足し合わせる計算を考えてみましょう。 数学的には 0.1×100=10.00.1 \times 100 = 10.0 となりますが、浮動小数点数でこれを計算すると、わずかに 10.010.0 からずれた値になることがあります。 一方、0.125 のように正確に表現できる数をいくら足し合わせても、誤差は生じません。 このことから、浮動小数点数の計算結果には常に誤差が含まれる可能性があることを認識しておく必要があります。

4.2 その他の誤差の発生源と対策

丸め誤差以外にも、コンピュータシミュレーションには様々な誤差の発生源があります。

4.2.1 オーバーフロー (Overflow) とアンダーフロー (Underflow)

これらの誤差は、計算結果が予期せぬ大きな値や小さな値になった場合に生じます。

4.2.2 桁落ち (Loss of Significance)

ほぼ等しい数値同士の引き算を行うと、有効桁数が大幅に失われる現象を桁落ちと呼びます。 例: 541325\sqrt{41} - 32 の計算を考えます。 416.40312423743\sqrt{41} \approx 6.40312423743 54132.015621187155\sqrt{41} \approx 32.01562118715 もし計算が4桁の有効数字で行われるとします。 54132.025\sqrt{41} \approx 32.02 32.0232.00=0.0232.02 - 32.00 = 0.02 この結果は、もとの値が持っていた有効桁の多くを失い、1桁しか有効数字が残っていません。このような計算は避けるべきです。 対策としては、数式を変形して引き算を回避するなどの方法があります。 例えば、x2+1x\sqrt{x^{2} + 1} - x のような式は、 (x2+1x)(x2+1+x)x2+1+x=(x2+1)x2x2+1+x=1x2+1+x\frac{(\sqrt{x^{2} + 1} - x)(\sqrt{x^{2} + 1} + x)}{\sqrt{x^{2} + 1} + x} = \frac{(x^{2} + 1) - x^{2}}{\sqrt{x^{2} + 1} + x} = \frac{1}{\sqrt{x^{2} + 1} + x} と変形することで桁落ちを回避できます。

4.2.3 情報落ち (Catastrophic Cancellation / Loss of Information)

絶対値が非常に異なる数値同士の加算や減算を行うと、絶対値の小さい方の情報が失われる現象を情報落ちと呼びます。 例: 1000 に 1.456 を加える計算を考えます。 もしコンピュータが4桁の有効数字でしか計算できないとすると、 1000+1.4561001.45610011000 + 1.456 \approx 1001.456 \rightarrow 1001 (4桁に丸め) この結果では、元の 0.4560.456 という情報が失われてしまいます。 幸い、現在のコンピュータでは64ビット浮動小数点数が主流であり、約15~17桁の有効桁数があるため、このような極端な情報落ちはほとんど発生しません。しかし、多数の計算を繰り返す場合には影響が出る可能性があるので、注意が必要です。

4.2.4 打ち切り誤差 (Truncation Error)

無限級数や連続的な関数を有限の項で打ち切って近似することで生じる誤差を打ち切り誤差と呼びます。 例: 関数をテイラー展開で近似する場合。 f(x)=f(a)+f(a)(xa)+f(a)2!(xa)2++f(n)(a)n!(xa)n+Rn+1f(x) = f(a) + f'(a)(x - a) + \frac{f''(a)}{2!}(x - a)^{2} + \ldots + \frac{f^{(n)}(a)}{n!}(x - a)^{n} + R_{n + 1} テイラー展開は無限項の和ですが、コンピュータで計算する際には有限項で打ち切らざるを得ません。この打ち切った部分が打ち切り誤差となります。

4.2.5 収束誤差 (Convergence Error)

繰り返し計算(イテレーション)によって解を求める自己無撞着計算(Self-Consistent Field calculation)などにおいて、計算を有限回で打ち切ることで生じる誤差を収束誤差と呼びます。理想的には無限回繰り返せば厳密な解が得られますが、実際には計算コストの制約から、ある程度の許容誤差に達した時点で計算を終了します。

4.2.6 モデル誤差 (Model Error)

物理現象をシミュレートする際に、物理モデルそのものに近似が含まれている場合に生じる誤差です。これは数値計算による誤差とは異なり、モデルの不完全性や単純化に起因します。

4.3 誤差を回避するためのプログラミングのヒント

4.3.1 浮動小数点数の等価比較

浮動小数点数は丸め誤差を含むため、厳密な等価比較 (==) は避けるべきです。 例えば、x * 10.0 == 30.0 のような比較は、x * 10.0 の計算結果が 30.030.0 にわずかに足りなかったり、超えたりすることがあるため、期待通りに動作しないことがあります。 代わりに、許容誤差 (epsilon, ϵ\epsilon) を用いて比較します。 | (計算結果) - (期待値) | < epsilon 例: abs(x * 10.0 - 30.0) < 1e-10 のように、絶対値の差が非常に小さな値 (ϵ\epsilon) より小さいかどうかで判断します。

4.3.2 浮動小数点数から整数への型変換

浮動小数点数を整数型に変換する際にも注意が必要です。 例えば、value10.010.0 であるはずが、コンピュータ内部では丸め誤差によってわずかに 9.9999999999999999.999999999999999 のような値になっていることがあります。このとき、int(value) のような関数を使用すると、結果が 99 になってしまう可能性があります。 これを回避するためには、やはり許容誤差 ϵ\epsilon を利用します。 int(value + epsilon) このようにわずかに正の値を加えることで、期待される値が 1010 であれば 1010 に、それより小さければ 99 にと、意図した通りの変換結果が得られやすくなります。

4.3.3 数値的に不安定な計算の回避

テイラー展開における情報落ちの例: exe^{- x} の値をテイラー展開で計算する場合を考えます。 ex=n=0(x)nn!=1x+x22!x33!+e^{- x} = \sum_{n = 0}^{\infty}\frac{( - x)^{n}}{n!} = 1 - x + \frac{x^{2}}{2!} - \frac{x^{3}}{3!} + \ldots もし xx が大きな正の値(例: x=39x = 39)の場合、偶数項は非常に大きな正の値に、奇数項は非常に大きな負の値になります。そして、これらの大きな値同士を足し引きすることで、桁落ちや情報落ちが発生し、最終的な結果の精度が著しく損なわれることがあります。 例えば、e39e^{- 39} は数学的には 4.25×10184.25 \times 10^{- 18} という極めて小さな値ですが、上記のテイラー展開を直接計算すると、Pythonでも 5.88116655.8811665 のような全く異なる値に収束してしまうことがあります。これは、途中で大きな正負の数が相殺し合う際に有効桁が失われたためです。

このような場合は、数値的に安定な計算方法を選択することが重要です。 ex=1exe^{- x} = \frac{1}{e^{x}} と変形し、exe^{x} をテイラー展開で計算します。 ex=n=0xnn!=1+x+x22!+x33!+e^{x} = \sum_{n = 0}^{\infty}\frac{x^{n}}{n!} = 1 + x + \frac{x^{2}}{2!} + \frac{x^{3}}{3!} + \ldots この場合、全ての項が正の値となるため、大きな正負の数同士の引き算による桁落ちや情報落ちは発生しません。結果として、e39e^{- 39} の計算でも正確な 4.25×10184.25 \times 10^{- 18} に収束することが期待できます。

コンピュータシミュレーションプログラムを開発する際には、常にこれらの誤差の発生源を意識し、適切な対策を講じることが重要です。


第5章 まとめと課題

本日の講義では、コンピュータにおける数値表現の基礎から、データ単位、数値型、そして数値計算に潜む様々な誤差について学習しました。特に浮動小数点数の表現限界、丸め誤差、桁落ち、情報落ち、打ち切り誤差、収束誤差といった概念は、シミュレーションの精度に直結する非常に重要なポイントです。

皆さんは本日出題された課題に取り組み、これらの概念を実践的に理解してください。

課題提出は、6月11日(水)の深夜23時59分までにLMSを通じてお願いします。

以上で本日の講義を終了します。質問があれば随時受け付けます。