C言語で級数を教えて!
こういった悩みにお答えします.
本記事の信頼性
- リアルタイムシステムの研究歴12年.
- 東大教員の時に,英語でOS(Linuxカーネル)の授業.
- 2012年9月~2013年8月にアメリカのノースカロライナ大学チャペルヒル校(UNC)コンピュータサイエンス学部で客員研究員として勤務.C言語でリアルタイムLinuxの研究開発.
- プログラミング歴15年以上,習得している言語: C/C++,Python,Solidity/Vyper,Java,Ruby,Go,Rust,D,HTML/CSS/JS/PHP,MATLAB,Verse(UEFN), Assembler (x64,ARM).
- 東大教員の時に,C++言語で開発した「LLVMコンパイラの拡張」,C言語で開発した独自のリアルタイムOS「Mcube Kernel」をGitHubにオープンソースとして公開.
- 2020年1月~現在はアメリカのノースカロライナ州チャペルヒルにあるGuarantee Happiness LLCのCTOとしてECサイト開発やWeb/SNSマーケティングの業務.2022年6月~現在はアメリカのノースカロライナ州チャペルヒルにあるJapanese Tar Heel, Inc.のCEO兼CTO.
- 最近は自然言語処理AIとイーサリアムに関する有益な情報発信に従事.
- (AI全般を含む)自然言語処理AIの論文の日本語訳や,AIチャットボット(ChatGPT,Auto-GPT,Gemini(旧Bard)など)の記事を50本以上執筆.アメリカのサンフランシスコ(広義のシリコンバレー)の会社でプロンプトエンジニア・マネージャー・Quality Assurance(QA)の業務委託の経験あり.
- (スマートコントラクトのプログラミングを含む)イーサリアムや仮想通貨全般の記事を200本以上執筆.イギリスのロンドンの会社で仮想通貨の英語の記事を日本語に翻訳する業務委託の経験あり.
こういった私から学べます.
C言語を独学で習得することは難しいです.
私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.
私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!
独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!
目次
級数
級数とは,数や関数など互いに足すことのできる数学的対象の列の無限項の和のことです.
初項\(a_1\)から第n項(nは自然数)\(a_n\)までの級数の総和は以下になります.
$$S_n = \sum_{i=1}^n a_i = a_1 + ... + a_n$$
nの値が無限大(∞)の場合は無限級数になり,そうでない場合は有限級数となります.
コンピュータでは無限項の和は表現できないので,n個の和の計算による有限級数となります.
無限級数で収束する場合,nの値をできるだけ大きくすることで真の値の近似値を数値解析します.
数学では計算の最終結果がわかりますが,コンピュータによる数値解析では真の値に近づいていく過程がわかります.
自然数の和
最もシンプルな級数といえば,1からnまでの自然数の和ですね.
その級数は下式になります.
$$S_n = \sum_{i=1}^n i = 1 + 2 + 3 + ... + n = \frac{n(n+1)}{2}$$
1からnまでの自然数の和を計算するコードは以下になります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> int main(void) { unsigned long i, n, sum; do { printf("Please input a natural number: "); scanf("%lu", &n); } while (n == 0); sum = 0; for (i = 1; i <= n; i++) { sum += i; } printf("sum of [%lu,%lu] = %lu\n", 1UL, n, sum); printf("(n * (n + 1)) / 2 = %lu\n", (n * (n + 1)) / 2); return 0; } |
実行結果は以下になります.
3行目の行末に10を入力した場合,1~10までに総和と(n * (n + 1)) / 2の計算結果が両方とも55になっていることがわかります.
1 2 3 4 5 |
$ gcc sum.c $ a.out Please input a natural number: 10 sum of [1,10] = 55 (n * (n + 1)) / 2 = 55 |
nの値を大きくするとオーバーフローが発生し,unsigned long型のような符号なし整数の場合は0になります.
これに対して,浮動小数点数でオーバーフローが発生した場合は無限大になります.
オーバーフローは以下の記事に詳しく記載してあります.
1に収束する分数の和
1に収束する分数の和として下式の級数があります.
$$S_n = \sum_{n=1}^{\infty} \frac{1}{2n} = \frac{1}{2} + \frac{1}{4} + \frac{1}{8} + \frac{1}{16} + ... = 1$$
1に収束する分数の和のコードは以下になります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> #define N 65536 int main(void) { size_t i; double d = 0.0; for (i = 2; i <= N; i *= 2) { d += 1.0 / i; printf("%lf\n", d); } return 0; } |
実行結果は以下になります.
1に収束していることがわかります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
$ gcc one.c $ a.out 0.500000 0.750000 0.875000 0.937500 0.968750 0.984375 0.992188 0.996094 0.998047 0.999023 0.999512 0.999756 0.999878 0.999939 0.999969 0.999985 |
バーゼル問題(オイラー級数)
バーゼル問題(オイラー級数)とは,平方数の逆数の1~∞の全ての和は何かという級数の問題の一つです.
証明は省略しますが,答えは以下になります.
$$S_n = \sum_{n=1}^{\infty} \frac{1}{n^2} = \lim_{n \to \infty} \left( \frac{1}{1^2} + \frac{1}{2^2} + ... + \frac{1}{n^2} \right) = \frac{\pi^2}{6} = 1.644934066848226436472...$$
C言語のfloat/double/long double型でバーゼル問題を計算するコードは以下になります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> #define N 10000000 #define PRECISION 50 int main(void) { float f = 0.0; double d = 0.0; long double ld = 0.0; size_t i; for (i = 1; i <= N; i++) { f += (float) 1.0 / (i * i); d += (double) 1.0 / (i * i); ld += (long double) 1.0 / (i * i); } printf("f = %.*f\n", PRECISION, f); printf("d = %.*lf\n", PRECISION, d); printf("ld = %.*Lf\n", PRECISION, ld); return 0; } |
実行結果は以下になります.
long double型が真の値(1.644934066848226436472...)に一番近いことがわかります.
1 2 3 4 5 |
$ gcc basel.c $ a.out f = 1.64472532272338867187500000000000000000000000000000 d = 1.64493396684725956546913039346691220998764038085938 ld = 1.64493396684823148647201090932767897356825415045023 |
ネイピア数
ネイピア数(e = 2.718281828459045235360287471352…)は,テイラー展開(0を中心とした級数なのでマクローリン展開)で計算することができます.
$$e^x = \sum_{n=0}^{\infty} \frac{x^n}{n!}$$
x = 1の場合は以下の級数にテイラー展開されます.
\begin{eqnarray*}
e &=& \frac{1^0}{0!} + \frac{1^1}{1!} + \frac{1^2}{2!} + \frac{1^3}{3!} ... \\
&=& 1 + 1 + \frac{1}{2} + \frac{1}{6} ... \\
\end{eqnarray*}
ネイピア数を計算するコードは以下になります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> #define N 65 #define PRECISION 50 int main(void) { float f = 1.0; double d = 1.0; long double ld = 1.0; size_t fact = 1; size_t i; for (i = 1; i <= N; i++) { fact *= i; f += (float) 1.0 / fact; d += (double) 1.0 / fact; ld += (long double) 1.0 / fact; } printf("f = %.*f\n", PRECISION, f); printf("d = %.*lf\n", PRECISION, d); printf("ld = %.*Lf\n", PRECISION, ld); return 0; } |
実行結果は以下になります.
long double型が真の値 (e = 2.718281828459045235360287471352…) に一番近いことがわかります.
1 2 3 4 5 |
$ gcc napier.c $ a.out f = 2.71828198432922363281250000000000000000000000000000 d = 2.71828182845904553488480814849026501178741455078125 ld = 2.71828182845904524865543461231709443381987512111664 |
まとめ
C言語で級数として,自然数の和,1に収束する分数の和,バーゼル問題(オイラー級数),ネイピア数を紹介しました.
級数はコンピュータの数値解析の基本ですので,きちんと習得しましょう.
C言語を独学で習得することは難しいです.
私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.
私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!
独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!