半導体工学における数値計算の基礎
第1章 講義の概要と導入
1.1 講義の進め方と評価
本講義では、コンピュータを用いた解析やシミュレーションプログラムを理解し、開発するために必要な数値解析(Numerical
Analysis)の基礎について解説します。私(担当教員)が前半の第1回から第7回までを担当し、コンピュータシミュレーションの基本と計算における誤差の発生源について説明します。
- 評価方法:
期末試験は実施せず、期末課題を提出していただきます。
- AIツールの利用:
ChatGPTのような生成AIの利用は許可しますが、提出物には皆さん自身の考察やAIの回答からの改善点を必ず含めてください。AIの回答をそのまま提出した場合は評価の対象外とします。
- 欠席時の対応:
欠席する場合は事前に連絡をお願いします。各講義は録画しており、後から視聴が必要な場合はメールまたはSlackでご連絡ください。
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問です。
- 基数変換:
- 2進数
101001
を10進数に変換してください。
- 10進数
4251
を16進数に変換してください。
この変換方法は、本日の講義で詳しく解説します。
- Pythonプログラムの解析:
- 本日提供される講義資料のZIPファイルに含まれるPythonプログラムの中から1つを選び、そのソースコードの各ブロックが何をしているのかを説明してください。
- もし理解できない部分があれば、「この部分は理解できませんでしたが、何のために必要なのでしょうか」といった形で疑問点を挙げてください。
- プログラムの内容が全く理解できなくても、「何も理解できませんでした」という回答でも構いません。重要なのは、プログラムに触れてみることです。
第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
という数は以下のように表現されます。
ここで「10」が基数(Base)です。
同様に、2進数で表現された数も、基数を「2」とすることで10進数に変換できます。例えば、2進数
11011
は以下のようになります。
したがって、2進数 11011
は10進数で 27
に対応します。
一般化された変換式: R進数で表現された数
は、10進数にすると以下のようになります。
2.2.2 10進数からR進数への変換
R進数から10進数への変換は上記の式で比較的容易ですが、その逆、つまり10進数からR進数への変換は少し複雑です。これは繰り返し除算の原理を用いて行います。
例として、10進数 374
を8進数(基数8)に変換する手順を見てみましょう。
374
を 8
で割ります。
374 = 8 × 46 + 6
(余り 6
) この余り
6
が8進数の最下位桁(右端)になります。
商の 46
を再び 8
で割ります。
46 = 8 × 5 + 6
(余り 6
) この余り
6
が8進数の2桁目になります。
商の 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)が利用されます。
8進数(基数8):
1桁で8種類の数字(0から7)を表現します。2進数の3桁が8進数の1桁に対応します
(
のため)。 例: 8進数 53
は、
(10進数) となります。
16進数(基数16):
1桁で16種類の文字を表現します。0から9の数字に加え、AからFのアルファベットが用いられます。Aは10、Bは11、…、Fは15に対応します。2進数の4桁が16進数の1桁に対応します
(
のため)。 例: 16進数 2F
は、
(10進数) となります。 2桁の16進数 FF
は、
(10進数) となり、これは8ビットで表現できる最大値に相当します。
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)と呼びます。
- 1バイト = 8ビット:
1バイトで表現できる値の範囲は、
種類の状態、つまり0から255までの整数です。
- KB (キロバイト) と KiB (キビバイト):
- コンピュータの文脈で「KB(キロバイト)」と表記された場合、通常は
バイト、つまり 1024バイト
を指します。これは国際単位系(SI)のキロ(1000)とは異なります。正確には
KiB(キビバイト)
と表記されるべきですが、一般的なコンピュータの教科書では大文字のBがバイトを、小文字のbがビットを表し、K、M、G、Tは2の冪乗を意味することが多いです。
- 1KB =
バイト = 1024バイト
- 1MB =
バイト = 1,048,576バイト
- 1GB =
バイト = 1,073,741,824バイト
- 1TB =
バイト = 1,099,511,627,776バイト
SI接頭辞(1000倍)と2の冪乗(1024倍)の違いは、容量が大きくなるほど顕著になります。
3.2 数値型
コンピュータプログラムでは、様々な種類の数値を扱うために、数値型(Data
Type)を使い分けます。主なものに整数型と浮動小数点型があります。
3.2.1 整数型 (Integer Type)
整数型は小数点以下の値を持たない数(例: 1, 100,
-5)を扱います。整数型は、割り当てられるビット長によって表現できる数値の範囲が異なります。また、負の数を扱うか否か(符号の有無)によっても分類されます。
- 16ビット整数型:
- 符号なし整数 (Unsigned Integer): 0から
までの値を表現できます。つまり、0から65535までです。
- 符号あり整数 (Signed Integer):
負の数も表現でき、
から
までの値を表現します。つまり、-32768から32767までです。
- 32ビット整数型:
- 符号なし整数: 0から
(約4.29
)
までの値を表現できます。
- 符号あり整数:
から
(約
)
までの値を表現できます。
- 64ビット整数型:
- 現在のCPUの主流は64ビットであり、一般的に64ビット整数型が標準的に使用されます。
- 符号なし整数 (Unsigned Long Long Integer): 0から
(約
)
までの値を表現できます。
- 符号あり整数 (Signed Long Long Integer):
から
(約
)
までの値を表現できます。
日本のGDP(約5兆USドル)のような巨大な金額を正確に扱うには、16桁程度の精度が必要となり、64ビット整数型が適切です。円周率の桁数計算のような、さらに巨大な整数を扱う場合は、標準の整数型では表現しきれないため、多倍長演算といったソフトウェア的な処理が必要になります。
3.2.2 浮動小数点型
(Floating-Point Type)
浮動小数点型は、小数点以下の値を持つ実数(例: 3.14,
-0.001)を扱います。コンピュータでは、実数を「符号部」「指数部」「仮数部」に分けて表現します。
- IEEE 754 規格: 浮動小数点数の表現は、IEEE
754という国際標準で定められています。主なものに以下の2種類があります。
- 単精度浮動小数点数 (Binary32):
32ビットを使用。
- 倍精度浮動小数点数 (Binary64):
64ビットを使用。
- より高い精度が必要な場合は、四倍精度 (Binary128)
なども存在します。
- Binary64 (倍精度) の構成例:
- 符号部 (Sign): 1ビット(正負を表す)。
- 指数部 (Exponent):
11ビット(数値の大きさのオーダーを表す)。
- 仮数部 (Fraction/Mantissa):
52ビット(数値の有効数字部分を表す)。 これにより、約
から
までの範囲の数を表現でき、有効桁数は約15~17桁に相当します
()。
- 精度の重要性:
- 原子のエネルギー(水素原子の1s軌道エネルギーは13.6
eV)から、室温での熱エネルギー(約62 meV)、磁気エネルギー(数
meV)といった物理現象のエネルギーは、非常に広い範囲にわたります。
- これらを統一的に扱う場合、meV(ミリ電子ボルト)からMeV(メガ電子ボルト)までの9桁以上の精度が必要になります。
- 単精度(32ビット)浮動小数点数では有効桁数が約7桁しかないため、この要求を満たすことができません。
- そのため、少なくとも倍精度(64ビット)浮動小数点数を使用することが不可欠であり、計算によっては四倍精度や多倍長演算が必要となる場合もあります。
- 例: ボルツマン因子 シリコンのバンドギャップ1.1
eV、室温での熱エネルギー
meV の場合、ボルツマン因子
は約
となります。 ワイドバンドギャップ材料(バンドギャップ4 eV)であれば約
、極低温(3
K)であれば
といった極めて小さな値になります。
倍精度浮動小数点数で表現できる最小値は約
ですから、
のような値は倍精度では扱えません。このような場合に四倍精度(約
まで対応)やそれ以上の精度が必要となります。しかし、これらの高精度演算はCPUハードウェアで直接サポートされていないことが多く、ソフトウェアで実装されるため、計算速度は大幅に低下します。
第4章 数値計算における誤差
4.1
浮動小数点数表現の限界と丸め誤差
実数には無限の桁数を持つものがありますが、コンピュータの浮動小数点型変数は有限のビット長しか持たないため、すべての実数を正確に表現することは不可能です。これにより生じる誤差を丸め誤差
(Rounding Error) と呼びます。
コンピュータ内部ではすべての数値が2進数で表現されます。浮動小数点数は一般的に
の形式で表現されます。
- 正確に表現できる例:
-
これらは2進数で有限桁の仮数部で表現できるため、コンピュータ上で正確な値として扱われます。
- 正確に表現できない例:
-
(10進数) は、2進数で表現すると
となり、無限に続く循環小数になります。 このため、コンピュータは
を有限桁数で近似して表現することになり、わずかな誤差(丸め誤差)を含みます。
4.1.1 丸め誤差の累積
0.1
のような近似値を使って計算を繰り返すと、丸め誤差が累積し、最終結果に大きな影響を与えることがあります。
例えば、0.1
を100回足し合わせる計算を考えてみましょう。
数学的には
となりますが、浮動小数点数でこれを計算すると、わずかに
からずれた値になることがあります。 一方、0.125
のように正確に表現できる数をいくら足し合わせても、誤差は生じません。
このことから、浮動小数点数の計算結果には常に誤差が含まれる可能性があることを認識しておく必要があります。
4.2 その他の誤差の発生源と対策
丸め誤差以外にも、コンピュータシミュレーションには様々な誤差の発生源があります。
4.2.1
オーバーフロー (Overflow) とアンダーフロー (Underflow)
- オーバーフロー:
変数型で表現できる最大値を超えるような大きな数値を扱おうとすると発生します。
- アンダーフロー:
変数型で表現できる最小値(0に近い極めて小さな数)を下回るような数値を扱おうとすると発生します。この場合、値が0として扱われてしまい、情報が失われます。
これらの誤差は、計算結果が予期せぬ大きな値や小さな値になった場合に生じます。
4.2.2 桁落ち (Loss of
Significance)
ほぼ等しい数値同士の引き算を行うと、有効桁数が大幅に失われる現象を桁落ちと呼びます。
例:
の計算を考えます。
もし計算が4桁の有効数字で行われるとします。
この結果は、もとの値が持っていた有効桁の多くを失い、1桁しか有効数字が残っていません。このような計算は避けるべきです。
対策としては、数式を変形して引き算を回避するなどの方法があります。
例えば、
のような式は、
と変形することで桁落ちを回避できます。
絶対値が非常に異なる数値同士の加算や減算を行うと、絶対値の小さい方の情報が失われる現象を情報落ちと呼びます。
例: 1000 に 1.456 を加える計算を考えます。
もしコンピュータが4桁の有効数字でしか計算できないとすると、
(4桁に丸め) この結果では、元の
という情報が失われてしまいます。
幸い、現在のコンピュータでは64ビット浮動小数点数が主流であり、約15~17桁の有効桁数があるため、このような極端な情報落ちはほとんど発生しません。しかし、多数の計算を繰り返す場合には影響が出る可能性があるので、注意が必要です。
4.2.4 打ち切り誤差 (Truncation
Error)
無限級数や連続的な関数を有限の項で打ち切って近似することで生じる誤差を打ち切り誤差と呼びます。
例: 関数をテイラー展開で近似する場合。
テイラー展開は無限項の和ですが、コンピュータで計算する際には有限項で打ち切らざるを得ません。この打ち切った部分が打ち切り誤差となります。
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
の計算結果が
にわずかに足りなかったり、超えたりすることがあるため、期待通りに動作しないことがあります。
代わりに、許容誤差 (epsilon,
)
を用いて比較します。
|
(計算結果)
-
(期待値)
| < epsilon
例: abs(x * 10.0 - 30.0) < 1e-10
のように、絶対値の差が非常に小さな値
()
より小さいかどうかで判断します。
4.3.2
浮動小数点数から整数への型変換
浮動小数点数を整数型に変換する際にも注意が必要です。
例えば、value
が
であるはずが、コンピュータ内部では丸め誤差によってわずかに
のような値になっていることがあります。このとき、int(value)
のような関数を使用すると、結果が
になってしまう可能性があります。 これを回避するためには、やはり許容誤差
を利用します。 int(value + epsilon)
このようにわずかに正の値を加えることで、期待される値が
であれば
に、それより小さければ
にと、意図した通りの変換結果が得られやすくなります。
4.3.3
数値的に不安定な計算の回避
テイラー展開における情報落ちの例:
の値をテイラー展開で計算する場合を考えます。
もし
が大きな正の値(例:
)の場合、偶数項は非常に大きな正の値に、奇数項は非常に大きな負の値になります。そして、これらの大きな値同士を足し引きすることで、桁落ちや情報落ちが発生し、最終的な結果の精度が著しく損なわれることがあります。
例えば、
は数学的には
という極めて小さな値ですが、上記のテイラー展開を直接計算すると、Pythonでも
のような全く異なる値に収束してしまうことがあります。これは、途中で大きな正負の数が相殺し合う際に有効桁が失われたためです。
このような場合は、数値的に安定な計算方法を選択することが重要です。
と変形し、
をテイラー展開で計算します。
この場合、全ての項が正の値となるため、大きな正負の数同士の引き算による桁落ちや情報落ちは発生しません。結果として、
の計算でも正確な
に収束することが期待できます。
コンピュータシミュレーションプログラムを開発する際には、常にこれらの誤差の発生源を意識し、適切な対策を講じることが重要です。
第5章 まとめと課題
本日の講義では、コンピュータにおける数値表現の基礎から、データ単位、数値型、そして数値計算に潜む様々な誤差について学習しました。特に浮動小数点数の表現限界、丸め誤差、桁落ち、情報落ち、打ち切り誤差、収束誤差といった概念は、シミュレーションの精度に直結する非常に重要なポイントです。
皆さんは本日出題された課題に取り組み、これらの概念を実践的に理解してください。
- 課題1: 基数変換 (2進数から10進数、10進数から16進数)
- 計算過程を自身で導き出してください。
- 提供された
base.py
プログラムは、答え合わせのために利用してください。
- 課題2: Pythonプログラムの解析
- 提供されたPythonプログラムのいずれかを選び、その機能やコードの役割を理解する努力をしてください。
- 理解できた範囲で構いませんし、不明点があればそれを明確にしてください。
課題提出は、6月11日(水)の深夜23時59分までにLMSを通じてお願いします。
以上で本日の講義を終了します。質問があれば随時受け付けます。