diff --git a/000-preface.md b/000-preface.md index b3a8889..d199a2a 100644 --- a/000-preface.md +++ b/000-preface.md @@ -18,3 +18,7 @@ C++知識のブートストラップを意識した入門書の執筆はなか 本書の著者近影の撮影は、著者の古くからの友人でありプロのカメラマンである三浦大に撮影してもらった。 三浦大のWebサイト: + +
+江添亮 +
\ No newline at end of file diff --git a/002-build.md b/002-build.md index 78d71ff..ccb11fd 100644 --- a/002-build.md +++ b/002-build.md @@ -130,7 +130,7 @@ GCCのコンパイラーオプションをいくつか学んでいこう。 g++ -std=c++17 -Wall --pedantic-errors -o 出力ファイル名 入力ファイル名 ~~~ -ところで、GCCのオプションはとても多い。すべてを知りたい読者は、以下のようにしてgccのマニュアルを読むとよい。 +ところで、GCCのオプションはとても多い。すべてを知りたい読者は、以下のようにしてGCCのマニュアルを読むとよい。 ~~~ $ man gcc @@ -383,7 +383,7 @@ $ make run $ make clean ~~~ -これで生成されたファイルをすべて削除できる +これで生成されたファイルをすべて削除できる。 テキストエディターにはVimを使っているがわざわざVimからターミナルに戻るのが面倒だ。 @@ -391,7 +391,7 @@ $ make clean :make ~~~ -VimはノーマルモードからMakeを呼び出すことができる。もちろん、`:make run`や`:make clean`もできる +VimはノーマルモードからMakeを呼び出すことができる。もちろん、`:make run`や`:make clean`もできる。 ### 依存関係を記述するルール diff --git a/003-guide-to-c++.md b/003-guide-to-c++.md index e07b272..ee91943 100644 --- a/003-guide-to-c++.md +++ b/003-guide-to-c++.md @@ -621,7 +621,7 @@ f is called. 実はラムダ式は本当のC++の`関数`ではない。本当の`関数`はとても書きづらいので心して読むべきだ。 -読者は本書の冒頭で使った`main関数`という言葉を覚えているだろうか。覚えていないとしても、サンプルコードに必ずと言って いいほど出てくる`main`という名前は気になっていたことだろう。 +読者は本書の冒頭で使った`main関数`という言葉を覚えているだろうか。覚えていないとしても、サンプルコードに必ずと言っていいほど出てくる`main`という名前は気になっていたことだろう。 ~~~cpp int main(){} diff --git a/004-debug-compile-error.md b/004-debug-compile-error.md index a7c4f02..8913713 100644 --- a/004-debug-compile-error.md +++ b/004-debug-compile-error.md @@ -11,7 +11,7 @@ + コンパイルエラーは普通 + コンパイルエラーが出たらありがとう -+ コンパイルエラーがでたら大喜び ++ コンパイルエラーが出たら大喜び 熟練のプログラマーは自分の書いたコードがコンパイルエラーを出さずに一発でコンパイルが通った場合、逆に不安になるくらいだ。 @@ -270,7 +270,7 @@ int main() ~~~c++ int main() { - // 引数を3つとって足して返す関数 + // 引数を3つ取って足して返す関数 auto f = [](auto a, auto b, auto c) { return a + b + c ; } ; @@ -278,7 +278,7 @@ int main() } ~~~ -GCCによるコンパイルエラーメッセージだけ抜粋すると以下のとおり、 +GCCによるコンパイルエラーメッセージだけ抜粋すると以下のとおり。 ~~~ main.cpp: In function ‘int main()’: @@ -301,7 +301,7 @@ main.cpp:7:40: error: expected ‘;’ before ‘)’ token 抜粋されたソースコードに示された問題の箇所、つまり7行目40列目にあるトークンは`')'`だ。この前に`';'`が必要とはどういうことだろう。 -問題を探るため、7行目のトークンを詳しく分解してみよう。以下は7行目と同じソースコードだが、トークンをわかりやすく分解してある +問題を探るため、7行目のトークンを詳しく分解してみよう。以下は7行目と同じソースコードだが、トークンをわかりやすく分解してある。 ~~~ std::cout << // 標準出力 diff --git a/005-the-restaurant-at-the-end-of-the-branch.md b/005-the-restaurant-at-the-end-of-the-branch.md index c6bfbfd..7ee0f11 100644 --- a/005-the-restaurant-at-the-end-of-the-branch.md +++ b/005-the-restaurant-at-the-end-of-the-branch.md @@ -834,7 +834,7 @@ true `bool`型の値と演算はこれで全部だ。値は`true`/`false`の2つのみ。演算は`==`, `!=`, `!`と`&&`と`||`の5つだけだ。 -読者の中には納得のいかないものもいるだろう。ちょっと待ってもらいたい。`bool`の大小比較できないのだろうか。`bool`の四則演算はできないのか。`"if(123)"`などと書けてしまうのはなんなのか。 +読者の中には納得のいかないものもいるだろう。ちょっと待ってもらいたい。`bool`の大小比較できないのだろうか。`bool`の四則演算はできないのか。`"if(123)"`などと書けてしまうのは何なのか。 好奇心旺盛な読者は本書の解説を待たずしてすでに自分でいろいろとコードを書いて試してしまっていることだろう。 @@ -850,7 +850,7 @@ int main() } ~~~ -このコードを実行すると、出力は`"false"`だ。`"true \< false"`の結果が`"false"`だということは、`true`は`false`より大きいということになる +このコードを実行すると、出力は`"false"`だ。`"true \< false"`の結果が`"false"`だということは、`true`は`false`より大きいということになる。 四則演算はどうか? diff --git a/008-loop.md b/008-loop.md index 52683a7..e56412e 100644 --- a/008-loop.md +++ b/008-loop.md @@ -126,7 +126,7 @@ skip : `2`を出力すべき文の実行が飛ばされていることがわかる。 -これだけみると`"if (false)"`と同じように見えるが、`goto文`はソースコードの上に飛ぶこともできるのだ。 +これだけだと`"if (false)"`と同じように見えるが、`goto文`はソースコードの上に飛ぶこともできるのだ。 ~~~cpp void hello() @@ -739,11 +739,11 @@ int main() } ~~~ -このコードでは、"`(x=1)`"と"`1`"が等しいか"`==`"どうかを判断している。"`(x=1)`"という式は変数`x`に`1`を代入する式だ。`代入式`の値は、代入された変数の値になる。この場合変数`x`の値だ。変数`x`には`1`が代入されているので、その値は1、つまり"`(x=1) == 1`"は"`1 == 1`"と書くのと同じ意味になる。この結果は`true`だ。 +このコードでは、"`(x=1)`"と"`1`"が等しい"`==`"かどうかを判断している。"`(x=1)`"という式は変数`x`に`1`を代入する式だ。`代入式`の値は、代入された変数の値になる。この場合変数`x`の値だ。変数`x`には`1`が代入されているので、その値は1、つまり"`(x=1) == 1`"は"`1 == 1`"と書くのと同じ意味になる。この結果は`true`だ。 さて、このことを踏まえて、"`( x = input() ) != 0`"を考えてみよう。 -"`( x = input() )`"は変数`x`に関数`input`を呼び出した結果を代入している。関数`input`はユーザーから入力を得て、その入力をそのまま返す。つまり変数`x`にはユーザーの入力した値が代入される。その結果が`0`と等しくないか"`!=`"どうかを判断している。つまり、ユーザーが`0`を入力した場合は`false`、非ゼロを入力した場合は`true`となる。 +"`( x = input() )`"は変数`x`に関数`input`を呼び出した結果を代入している。関数`input`はユーザーから入力を得て、その入力をそのまま返す。つまり変数`x`にはユーザーの入力した値が代入される。その結果が`0`と等しくない"`!=`"かどうかを判断している。つまり、ユーザーが`0`を入力した場合は`false`、非ゼロを入力した場合は`true`となる。 `while(条件)`は`条件`が`true`となる場合に繰り返し実行をする。結果として、ユーザーが`0`を入力するまで繰り返し実行をするコードになる。 @@ -783,7 +783,7 @@ int main() `goto文`でインデックスループを書くときに学んだように、 1. `n < 0`ならば関数を終了 -2. 変数iを作り値を0にする +2. 変数`i`を作り値を0にする 3. `i != n`ならば繰り返し実行 4. 出力 5. `++i` @@ -801,7 +801,7 @@ void hello_n( int n ) // 2. 変数iを作り値を0にする int i = 0 ; - //3. i != nならば繰り返し実行 + // 3. i != nならば繰り返し実行 while( i != n ) { // 4. 出力 std::cout << "hello\n"s ; @@ -896,7 +896,7 @@ int main() 9*1 9*2 9*3 9*4 9*5 9*6 9*7 9*8 9*9 ~~~ -これをみると、`"a*b"`のうちの`a`を`1`から`9`までインクリメントし、それに対して`b`を`1`から`9`までインクリメントさせればよい。つまり、9回のインデックスループの中で9回のインデックスループを実行することになる。ループの中のループだ。 +これを見ると、`"a*b"`のうちの`a`を`1`から`9`までインクリメントし、それに対して`b`を`1`から`9`までインクリメントさせればよい。つまり、9回のインデックスループの中で9回のインデックスループを実行することになる。ループの中のループだ。 ~~~c++ while ( 条件 ) @@ -1403,7 +1403,7 @@ void f( int x ) { g( x+1 ) ; } int main() { f( 0 ) ; } ~~~ -これをみると、関数`main`は関数`f`に引数`0`を渡し、関数`f`は関数`g`に引数`1`を渡している。これをもっと再帰的に考えよう。 +これを見ると、関数`main`は関数`f`に引数`0`を渡し、関数`f`は関数`g`に引数`1`を渡している。これをもっと再帰的に考えよう。 ~~~cpp void until_ten( int x ) @@ -1555,7 +1555,7 @@ int convert( int n ) ~~~cpp // OK solve(10111101) ; -// ありえない +// あり得ない solve(2) ; ~~~ diff --git a/009-vector.md b/009-vector.md index 3f3aada..2688036 100644 --- a/009-vector.md +++ b/009-vector.md @@ -324,7 +324,7 @@ min = 4 `vector`の変数を`v`、要素数を`size`とする。変数`min`には現在わかっている中で最も小さい要素へのインデックスが代入される。 -1. 変数`min`に0を代入する。 +1. 変数`min`に0を代入する 2. `size`回のループを実行する 3. 変数`index`に`0`から`size-1`までの整数を代入する 4. `'v.at(index) < v.at(min)'`ならば`min = index` @@ -393,7 +393,7 @@ int main() ^ ~~~ -こんどは4番目の`3`だ。これも先頭と交換する +今度は4番目の`3`だ。これも先頭と交換する ~~~ 3 4 8 9 7 @@ -477,7 +477,7 @@ int main() 変数とまったく同じだ。 -しかし、変数`a`に変数bの値を代入すると、変数`a`の元の値は消えてしまう。 +しかし、変数`a`に変数`b`の値を代入すると、変数`a`の元の値は消えてしまう。 ~~~cpp int main() diff --git a/010-debug-printf.md b/010-debug-printf.md index 2129f5c..840da63 100644 --- a/010-debug-printf.md +++ b/010-debug-printf.md @@ -261,7 +261,7 @@ a = b ; // a = 1 b = a ; // b = 1 ~~~ -変数`a`, `b`の値を交換したい場合、変数`a`に変数`b`を代入したあとに、変数`b`に変数`a`を代入する処理は誤りだ。なぜならば、変数`b`の代入のときには、変数`a`の値は変数bの値になってしまっているからだ。 +変数`a`, `b`の値を交換したい場合、変数`a`に変数`b`を代入したあとに、変数`b`に変数`a`を代入する処理は誤りだ。なぜならば、変数`b`の代入のときには、変数`a`の値は変数`b`の値になってしまっているからだ。 前章で学んだように、こういう場合、別の変数に値を代入して退避させておく。 diff --git a/011-integer.md b/011-integer.md index d610197..2408449 100644 --- a/011-integer.md +++ b/011-integer.md @@ -246,8 +246,10 @@ $-1$は1の補数表現では、1(`0b00000001`)の各ビットを反転させた 同様に、$-2$は`0b11111110`に、$-3$は`0b11111101`になる。 + 2の補数表現の$-1$と$-2$を足すと以下のようになる。 diff --git a/016-algorithm.md b/016-algorithm.md index e015154..ca07399 100644 --- a/016-algorithm.md +++ b/016-algorithm.md @@ -251,7 +251,7 @@ int main() { std::vector v = {1,2,3,4,5} ; - // 引数をリファレンスでとって2倍にする関数 + // 引数をリファレンスで取って2倍にする関数 auto twice = [](auto & value){ value = 2 * value ; } ; std::for_each( std::begin(v), std::end(v), twice ) ; @@ -923,7 +923,7 @@ auto copy = []( auto first, auto last, auto result ) { *result = *iter ; } return result ; -} +} ; ~~~ @@ -940,7 +940,7 @@ auto transform = []( auto first, auto last, auto result, auto op ) { *result = op(*iter) ; } return result ; -} +} ; ~~~ 使い方は`copy`と似ているが、値をコピーをする際に関数を適用することができる。 @@ -1030,7 +1030,7 @@ auto fill_n = []( auto first, auto n, auto value ) { *first = value ; } -} +} ; ~~~ diff --git a/019-operator-overloading.md b/019-operator-overloading.md index d215d9b..d38bfac 100644 --- a/019-operator-overloading.md +++ b/019-operator-overloading.md @@ -481,7 +481,7 @@ int main() 分数クラスの足し算を考えよう。 + 分母が同じならば分子を足す -+ 分母が異なるならば互いの分母を掛けて、分母をそろえて足す。 ++ 分母が異なるならば互いの分母を掛けて、分母をそろえて足す コードにすると以下のようになる。 @@ -626,7 +626,6 @@ int main() 演算子としてではなく、関数と同じように呼び出すこともできる。 ~~~cpp - struct S { } ; // S f( S, S )のようなもの diff --git a/024-more-array.md b/024-more-array.md index 3092145..9861e9f 100644 --- a/024-more-array.md +++ b/024-more-array.md @@ -55,7 +55,7 @@ struct array using value_type = T ; using reference = T & ; - using size_type = std::size_t + using size_type = std::size_t ; value_type storage[N] ; diff --git a/025-array-iterator.md b/025-array-iterator.md index 63effbf..8b95f66 100644 --- a/025-array-iterator.md +++ b/025-array-iterator.md @@ -61,7 +61,7 @@ int main() ~~~cpp // イテレーターを表現するクラス -struct array_iterator { } +struct array_iterator { } ; template < typename T, std::size_t N > struct array @@ -189,7 +189,7 @@ struct array // 黒魔術2: *this // 黒魔術3: iterator(*this) { return iterator(*this) ; } -} +} ; ~~~ 黒魔術1は`array_iterator_begin`の中にある。この`array`は`array`と同じ意味になる。つまり全体としては、`array_iterator_begin>`と書いたものと同じだ。クラステンプレートの中でクラス名を使うと、テンプレート実引数をそれぞれ指定したものと同じになる。 @@ -343,7 +343,7 @@ struct array_iterator // 前の要素を指す array_iterator & operator --() ; - //いま参照している要素へのリファレンスを返す + // いま参照している要素へのリファレンスを返す Array::reference operator *() ; } ; ~~~ @@ -399,7 +399,7 @@ struct array_iterator array_iterator( Array & a, std::size_t i ) : a( a ), i(i) { } - //いま参照している要素へのリファレンスを返す + // いま参照している要素へのリファレンスを返す Array::reference operator *() { return a[i] ; @@ -1066,7 +1066,7 @@ struct array_const_iterator // コンストラクター array_const_iterator( Array const & a, std::size_t i ) - a(a), i(i) { } + : a(a), i(i) { } } ; ~~~ @@ -1097,7 +1097,7 @@ struct array_const_iterator // array_iteratorからの変換コンストラクター array_const_iterator( typename array_iterator::iterator const & iter ) - a( iter.a ), i( iter.i ) { } + : a( iter.a ), i( iter.i ) { } } ; ~~~ diff --git a/026-exception.md b/026-exception.md index 457ba91..0878a43 100644 --- a/026-exception.md +++ b/026-exception.md @@ -444,14 +444,14 @@ main is destructed. なぜこの順番に出力されるか考えてみよう。 -1. プログラムの実行は関数`main`から始まる。そのためまず`main`が構築される。 -2. 関数`main`は関数`g`を呼ぶ。`g`が構築される。 -3. 関数`g`は関数`f`を呼ぶ。`f`が構築される。 -4. 関数`f`は例外を投げるので、`f`は破棄される。 -5. 関数`g`に巻き戻ったが`catch`がないのでさらに巻き戻る。`g`が破棄される。 -6. 関数`main`に巻き戻ったところ対応する`catch`があるのでスタックアンワインディングは停止する。 -7. `caught.`が出力される。 -8. `main`が破棄される。 +1. プログラムの実行は関数`main`から始まる。そのためまず`main`が構築される +2. 関数`main`は関数`g`を呼ぶ。`g`が構築される +3. 関数`g`は関数`f`を呼ぶ。`f`が構築される +4. 関数`f`は例外を投げるので、`f`は破棄される +5. 関数`g`に巻き戻ったが`catch`がないのでさらに巻き戻る。`g`が破棄される +6. 関数`main`に巻き戻ったところ対応する`catch`があるのでスタックアンワインディングは停止する +7. `caught.`が出力される +8. `main`が破棄される 例外が投げられると通常の実行は飛ばされるので、例外が投げられるかもしれない処理のあとに、例外の有無にかかわらず絶対に実行したい処理がある場合は、クラスのデストラクターに書くとよい。 diff --git a/028-pointer-semantics.md b/028-pointer-semantics.md index a9ec1ee..72e6001 100644 --- a/028-pointer-semantics.md +++ b/028-pointer-semantics.md @@ -235,7 +235,7 @@ int * pointer = 0 ; ### 無効な参照先の作り方 -ポインターやリファレンスによって参照先が参照される時点では有効だったが、あとに無効になる参照先を作ることができてしまう。 +ポインターやリファレンスによって参照先が参照される時点では有効だったが、後に無効になる参照先を作ることができてしまう。 例えば以下のコードだ。 diff --git a/031-iterator-operations.md b/031-iterator-operations.md index 4c10ceb..552e0a7 100644 --- a/031-iterator-operations.md +++ b/031-iterator-operations.md @@ -14,7 +14,7 @@ struct array_iterator std::size_t i ; array_iterator( Array * a, std::size_t i ) - a(a), i(i) { } + : a(a), i(i) { } reference operator *() const { return a[i] ; } @@ -857,7 +857,7 @@ int main() 前方イテレーター以上のイテレーターの例として、`iota_iterator`を実装してみよう。 -このイテレーターはT型の整数を保持し、`operator *`でリファレンスを返し、`operator ++`でインクリメントする。 +このイテレーターは`T`型の整数を保持し、`operator *`でリファレンスを返し、`operator ++`でインクリメントする。 以下のように使える。 diff --git a/034-vector-memory-allocation.md b/034-vector-memory-allocation.md index 2a974a4..162372b 100644 --- a/034-vector-memory-allocation.md +++ b/034-vector-memory-allocation.md @@ -166,7 +166,7 @@ int main() ~~~cpp vector( const allocator_type & alloc ) noexcept - alloc( alloc ) + : alloc( alloc ) { } ~~~ diff --git a/035-copy.md b/035-copy.md index e987a42..c9a30c0 100644 --- a/035-copy.md +++ b/035-copy.md @@ -697,10 +697,10 @@ int main() まとめよう。 -1. 自分自身への代入であれば何もしない。 -2. 要素数が同じならば要素ごとにコピー代入。 -3. それ以外の場合で、予約数が十分ならば有効な要素にはコピー代入、残りはコピー構築。 -4. それ以外の場合で、予約数が不十分ならば、現在の要素はすべて破棄して新たなストレージを確保してコピー構築。 +1. 自分自身への代入であれば何もしない +2. 要素数が同じならば要素ごとにコピー代入 +3. それ以外の場合で、予約数が十分ならば有効な要素にはコピー代入、残りはコピー構築 +4. それ以外の場合で、予約数が不十分ならば、現在の要素はすべて破棄して新たなストレージを確保してコピー構築 ~~~cpp vector & operator = ( const vector & r ) diff --git a/043-random.md b/043-random.md index 6b23ccc..e2037e7 100644 --- a/043-random.md +++ b/043-random.md @@ -582,7 +582,7 @@ $$ P(i\,|\,a,b) = 1 / (b - a + 1) \text{ .} $$ -以下のように変数を宣言する。 +変数の宣言: ~~~c++ std::uniform_int_distribution d( a, b ) ; @@ -624,7 +624,7 @@ $$ `a == b`のときは未定義となる。 -以下のように変数を宣言する。 +変数の宣言: ~~~c++ std::uniform_real_distribution d( a, b ) ; @@ -673,8 +673,8 @@ void f( Engine & e ) 具体的なベルヌーイ試行の例を挙げると、 + コイントスの結果、表か、裏か -+ 6面ダイスを振って6がでるか、6以外が出るか -+ 6面ダイスを振って5,6がでるか、1,2,3,4が出るか ++ 6面ダイスを振って6が出るか、6以外が出るか ++ 6面ダイスを振って5,6が出るか、1,2,3,4が出るか + 確率1%で当たるくじ引きの結果がアタリか、ハズレか + 赤玉と白玉が多数入ったツボの中身をよくかき混ぜ、玉を1つだけ取り出し、戻す。引いた玉の色が赤か、白か @@ -712,7 +712,7 @@ $$ 確率$p$で`true`が、確率$1-p$で`false`が返る。 -以下のように変数を宣言する。 +変数の宣言: ~~~c++ std::bernoulli_distribution d( p ) ; @@ -720,7 +720,7 @@ std::bernoulli_distribution d( p ) ; `p`は`double`型で、値の範囲は$0 \leq p \leq 1$。 -使い方。 +使い方: ~~~cpp int main() @@ -734,7 +734,7 @@ int main() } ~~~ -`bernoulli_distribution`はテンプレートクラスではない。生成する乱数の型は`bool`だ。`p`は`double`型で確率$p$のことだ。値の範囲は$0 \leq p \leq 1$ +`bernoulli_distribution`はテンプレートクラスではない。生成する乱数の型は`bool`だ。`p`は`double`型で確率$p$のことだ。値の範囲は$0 \leq p \leq 1$。 例えば前述の32%の確率でアイテムが入っている宝箱を実装するには以下のようになる。 @@ -824,7 +824,7 @@ $$ P(i\,|\,t,p) = \binom{t}{i} \cdot p^i \cdot (1-p)^{t-i} \text{ .} $$ -以下のように変数を宣言する。 +変数の宣言: ~~~c++ std::binomial_distribution d( t, p ) ; @@ -832,7 +832,7 @@ std::binomial_distribution d( t, p ) ; `IntType`は整数型でデフォルトは`int`だ。`t`は`IntType`型の整数値で、値の範囲は$0 \leq t$だ。`p`は`double`型の値で確率を指定する。`p`の値の範囲は$0 \leq p \leq 1$だ。 -使い方。 +使い方: ~~~cpp int main() @@ -925,7 +925,7 @@ auto lootbox( Engine & e ) + 6面ダイスを1の目が出るまで振った回数 + 確率1%で当たるくじ引きをアタリが出るまで引いた回数 -コイントスの例で考えよう。コイントス1回をベルヌーイ試行とし、成功を表とする。表が出るまでコイントスをしてみよう。コイントスを何回する必要があるだろうか。運がよければ1回で表がでるので1回だ。運が悪ければ、5回コイントスをしても全部裏なこともあるだろう。100回コイントスをして表が一度も出ないことは、確率的にはありえる。ただしその確率は$\frac{1}{2^{100}}$なので、およそありえない確率ではある。 +コイントスの例で考えよう。コイントス1回をベルヌーイ試行とし、成功を表とする。表が出るまでコイントスをしてみよう。コイントスを何回する必要があるだろうか。運がよければ1回で表がでるので1回だ。運が悪ければ、5回コイントスをしても全部裏なこともあるだろう。100回コイントスをして表が一度も出ないことは、確率的にはあり得る。ただしその確率は$\frac{1}{2^{100}}$なので、およそあり得ない確率ではある。 `std::geometric_distribution`は`IntType`型の乱数$i$, $i \geq 0$を以下の離散確率関数に従って分布する。 @@ -933,7 +933,7 @@ $$ P(i\,|\,p) = p \cdot (1-p)^{i} \text{ .} $$ -変数の宣言。 +変数の宣言: ~~~c++ std::geometric_distribution d( p ) ; @@ -943,7 +943,7 @@ std::geometric_distribution d( p ) ; `geometric_distribution`の生成する乱数の範囲にも注意が必要だ。生成される乱数$i$の範囲は$i \geq 0$だ。0もあり得る。0ということは、最初のベルヌーイ試行が成功したということだ。1は2回目のベルヌーイ試行が成功したということだ。幾何分布はベルヌーイ試行が初めて成功するまでのベルヌーイ試行の回数を返すので、成功したベルヌーイ試行は回数に含めない。 -使い方。 +使い方: ~~~cpp int main() @@ -1040,7 +1040,7 @@ $$ $p = 1$のときの$P(i\,|\,k,p)$は未定義だ。 -変数の宣言は以下のとおり。 +変数の宣言: ~~~c++ std::negative_binomial_distribution d( k, p ) ; @@ -1048,7 +1048,7 @@ std::negative_binomial_distribution d( k, p ) ; `IntType`は整数型でデフォルトは`int`、`k`は`IntType`型の値$0 < k$で成功させるベルヌーイ試行の回数、`p`は`double`型の確率$- < p \leq 1$だ。 -使い方。 +使い方: ~~~cpp int main() diff --git a/044-random-part2.md b/044-random-part2.md index 16368b1..0f5c9fa 100644 --- a/044-random-part2.md +++ b/044-random-part2.md @@ -28,7 +28,7 @@ $$ ここで$\mu$を`mean`とする。$\mu > 0$ではない場合未定義だ。 -変数の宣言は以下のとおり。 +変数の宣言: ~~~c++ std::poisson_distribution d( mean ) ; @@ -36,7 +36,7 @@ std::poisson_distribution d( mean ) ; `T`は整数型でデフォルトは`int`、`mean`は`RealType`型。$\mu$と同じで浮動小数点数型の値で所定の時間に平均して発生する事象の回数だ。値の範囲は$0 < \text{mean}$。 -使い方。 +使い方: ~~~cpp int main() @@ -104,7 +104,7 @@ $$ p(x\,|\,\lambda) = \lambda e^{-\lambda x} \text{ .} $$ -変数の宣言方法は以下のとおり。 +変数の宣言: ~~~c++ std::exponential_distribution d( lambda ) ; @@ -114,7 +114,7 @@ std::exponential_distribution d( lambda ) ; `std::exponential_distribution`の生成する乱数は`1.0`のとき、ある時間間隔に等しくなる。`0.5`なら半分の時間間隔、`2.0`なら2倍の時間間隔だ。 -使い方。 +使い方: ~~~cpp int main() @@ -160,7 +160,7 @@ $$ $\alpha$を`alpha`、$\beta$を`beta`とする。 -変数の宣言は以下のとおり。 +変数の宣言: ~~~c++ std::gamma_distribution d( alpha, beta ) ; @@ -168,7 +168,7 @@ std::gamma_distribution d( alpha, beta ) ; `RealType`は浮動小数点数型でデフォルトは`double`。`alpha`, `beta`は`RealType`型。値の範囲は$0 < alpha$, $0 < beta$。 -使い方。 +使い方: ~~~cpp int main() @@ -193,7 +193,7 @@ p(x\,|\,a,b) = \frac{a}{b} \text{ .} $$ -変数の宣言は以下のとおり。 +変数の宣言: ~~~c++ std::weibull_distribution d( a, b ) ; @@ -201,7 +201,7 @@ std::weibull_distribution d( a, b ) ; `RealType`は浮動小数点数型でデフォルトは`double`。`a`, `b`は`RealType`型。値の範囲は$0 < a$, $0 < b$。 -使い方。 +使い方: ~~~cpp @@ -228,7 +228,7 @@ $$ 極値分布(extreme value distribution)は、ガンベルI型(Gumbel Type I)、対数ウェイブル(log-Weibull)、フィッシャー=ティペットI型(Fisher-Tippett Type I)という名前の分布と呼ばれることもある。 -変数の宣言は以下のとおり。 +変数の宣言: ~~~c++ std::extreme_value_distribution d( a, b ) ; @@ -236,7 +236,7 @@ std::extreme_value_distribution d( a, b ) ; `RealType`は浮動小数点数型でデフォルトは`double`。`a`, `b`は`RealType`型。値の範囲は$0 < b$。 -使い方。 +使い方: ~~~cpp int main() diff --git a/045-random-part3.md b/045-random-part3.md index 6f9d602..5ab5317 100644 --- a/045-random-part3.md +++ b/045-random-part3.md @@ -18,7 +18,7 @@ $$ 分布パラメーターのうちの$\mu$と$\sigma$は、それぞれ分布の平均(mean)、標準偏差(standard deviation)とも呼ばれている。 -変数の宣言。 +変数の宣言: ~~~c++ std::normal_distribution d( mean, stddev ) ; @@ -26,7 +26,7 @@ std::normal_distribution d( mean, stddev ) ; `RealType`は浮動小数点数型でデフォルトは`double`。`mean`, `stddev`は浮動小数点数型。`mean`は平均。`stddev`は標準偏差で値の範囲は$0 < \text{stddev}$。 -使い方。 +使い方: ~~~cpp int main() @@ -53,7 +53,7 @@ p(x\,|\,m,s) = \frac{1}{s x \sqrt{2 \pi}} \text{ .} $$ -変数の宣言。 +変数の宣言: ~~~c++ std::lognormal_distribution d( m, s ) ; @@ -61,7 +61,7 @@ std::lognormal_distribution d( m, s ) ; `RealType`は浮動小数点数型でデフォルトは`double`。`m`, `s`は`RealType`型。値の範囲は$0 < s$。 -使い方。 +使い方: ~~~cpp int main() @@ -86,7 +86,7 @@ $$ p(x\,|\,n) = \frac{x^{(n/2)-1} \cdot e^{-x/2}}{\Gamma(n/2) \cdot 2^{n/2}} \text{ .} $$ -変数の宣言。 +変数の宣言: ~~~c++ std::chi_squared_distribution d( n ) ; @@ -94,7 +94,7 @@ std::chi_squared_distribution d( n ) ; `RealType`は浮動小数点数型でデフォルトは`double`。`n`は`RealType`型。値の範囲は$0 < n$。 -使い方。 +使い方: ~~~cpp int main() @@ -118,7 +118,7 @@ $$ p(x\,|\,a,b) = \left(\pi b \left(1 + \left(\frac{x-a}{b} \right)^2 \, \right)\right)^{-1} \text{ .} $$ -変数の宣言。 +変数の宣言: ~~~c++ std::cauchy_distribution d( a, b ) ; @@ -126,7 +126,7 @@ std::cauchy_distribution d( a, b ) ; `RealType`は浮動小数点数型でデフォルトは`double`。`a`, `b`は`RealType`型。値の範囲は$0 < b$。 -使い方。 +使い方: ~~~cpp int main() @@ -157,7 +157,7 @@ p(x\,|\,m,n) = \frac{\Gamma\big((m+n)/2\big)}{\Gamma(m/2) \; \Gamma(n/2)} \text{ .} $$ -変数の宣言。 +変数の宣言: ~~~c++ std::fisher_f_distribution d( m, n ) ; @@ -166,7 +166,7 @@ std::fisher_f_distribution d( m, n ) ; `RealType`は浮動小数点数型でデフォルトは`dobule`。`m`, `n`は`RealType`型。値の範囲は$0 < m$ かつ $0 < n$。 -使い方。 +使い方: ~~~cpp int main() @@ -181,7 +181,7 @@ int main() ### スチューデントの$t$分布(`std::student_t_distribution`) -スチューデントの$t$分布(Student's $t$-distribution)はウィリアム・シーリー・ゴセットによって考案された。当時、ウィリアムはギネス醸造所で働いていたが、ギネスは従業員に科学論文を発表することを禁じていたために、ウィリアムはスチューデントという偽名で発表した。 +スチューデントの$t$分布(Student's $t$-distribution)はウィリアム・シーリー・ゴセット(William Sealy Gosset)によって考案された。当時、ウィリアムはギネス醸造所で働いていたが、ギネスは従業員に科学論文を発表することを禁じていたために、ウィリアムはスチューデントという偽名で発表した。 `std::student_t_distribution`は浮動小数点数型の乱数$x$を以下の確率密度関数に従って分布する。 @@ -192,7 +192,7 @@ p(x\,|\,n) = \frac{1}{\sqrt{n \pi}} \text{ .} $$ -変数の宣言。 +変数の宣言: ~~~c++ std::student_t_distribution d( n ) ; @@ -200,7 +200,7 @@ std::student_t_distribution d( n ) ; `RealType`は浮動小数点数型でデフォルトは`double`。`n`は`RealType`型で、値の範囲は$0 < n$。 -使い方。 +使い方: ~~~cpp int main() diff --git a/046-random-part4.md b/046-random-part4.md index 5dae42b..2ae198c 100644 --- a/046-random-part4.md +++ b/046-random-part4.md @@ -1,12 +1,12 @@ ## サンプリング分布(sampling distributions) -サンプリング分布(sampling distributions)とは、標本から分布の特徴が分かっている場合に、その特徴を指定することにより、望みの分布を作り出す分布のことだ。 +サンプリング分布(sampling distributions)とは、標本から分布の特徴がわかっている場合に、その特徴を指定することにより、望みの分布を作り出す分布のことだ。 ### 離散分布(`std::discrete_distribution`) #### 簡単な説明 -離散分布(discrete distribution)は整数型の乱数$i$, $0 \leq i < n$を返す分布だ。例えば$n = 10$ならば、$0,1,2,3,4,5,6,7,8,9$の10個のうちのいずれかの整数値を乱数として返す。この際、乱数値として取りうる整数値一つ一つに、確率を設定できる。確率は$p_0, \dotsc, p_{n-1}$で設定し、$p_0$が$0$の確率, $p_1$が$1$の確率...$p_{n-1}$が$n$の確率となる。それぞれの乱数$i$は確率$\frac{p_i}{S}$で出現する。このとき$S$とはすべての確率の合計、つまり$S = p_0 + \dotsc + p_{n-1}$となる。確率$p_i$は`double`型で与える。 +離散分布(discrete distribution)は整数型の乱数$i$, $0 \leq i < n$を返す分布だ。例えば$n = 10$ならば、$0,1,2,3,4,5,6,7,8,9$の10個のうちのいずれかの整数値を乱数として返す。この際、乱数値として取りうる整数値1つ1つに、確率を設定できる。確率は$p_0, \dotsc, p_{n-1}$で設定し、$p_0$が$0$の確率, $p_1$が$1$の確率...$p_{n-1}$が$n$の確率となる。それぞれの乱数$i$は確率$\frac{p_i}{S}$で出現する。このとき$S$とはすべての確率の合計、つまり$S = p_0 + \dotsc + p_{n-1}$となる。確率$p_i$は`double`型で与える。 たとえば、`{1.0, 1.0, 1.0}`という確率群を渡した場合、離散分布は$0, 1, 2$のいずれかの乱数をそれぞれ$\frac{1.0}{3.0}$の確率で返す。 @@ -32,7 +32,7 @@ $$ P(i \,|\, p_0, \dotsc, p_{n-1}) = p_i \text{ .} $$ -別に指定のない場合、分布パラメーターは$p_k = {w_k / S}$ for $k = 0, \dotsc, n - 1$として計算され、このとき値$w_k$は、一般に*ウエイト(weight)*と呼ばれていて、値は非負数、非NaN、非無限でなければならない。さらに、以下の関係が成り立たねばならない。$0 < S = w_0 + \dotsb + w_{n - 1}$ +別に指定のない場合、分布パラメーターは$p_k = {w_k / S}$ for $k = 0, \dotsc, n - 1$として計算され、このとき値$w_k$は、一般に*ウエイト(weight)*と呼ばれていて、値は非負数、非NaN、非無限でなければならない。さらに、以下の関係が成り立たねばならない。$0 < S = w_0 + \dotsb + w_{n - 1}$。 #### 変数の宣言 @@ -40,7 +40,7 @@ $$ ##### イテレーターのペア -変数の宣言。 +変数の宣言: ~~~c++ std::discrete_distribution d( firstW, lastW ) ; @@ -48,7 +48,7 @@ std::discrete_distribution d( firstW, lastW ) ; `IntType`は整数型でデフォルトは`int`、`[firstW, lastW)`はイテレーターのペアで、`double`型に変換可能な値を参照している。 -利用例。 +利用例: ~~~cpp int main() @@ -63,7 +63,7 @@ int main() ##### 初期化リスト -利用例。 +利用例: ~~~c++ std::discrete_distribution d( {...} ) ; @@ -72,7 +72,7 @@ std::discrete_distribution d = {...} ; `...`には`double`型の浮動小数点数を指定する -利用例。 +利用例: ~~~cpp int main() @@ -99,7 +99,7 @@ template ); ~~~ -`UnaryOperation`はひとつの実引数を取る関数オブジェクトで戻り値の型は`double`型に変換できること。さらに、`double`型は`UnaryOperation`の引数に変換可能なこと。もし$nw = 0$の場合は、$n = 1$とする。それ以外の場合、$n = \tcode{nw}$とする。このとき、$0 < \delta = (\tcode{xmax} - \tcode{xmin}) / n$となる関係が満たされなければならない。 +`UnaryOperation`は1つの実引数を取る関数オブジェクトで戻り値の型は`double`型に変換できること。さらに、`double`型は`UnaryOperation`の引数に変換可能なこと。もし$nw = 0$の場合は、$n = 1$とする。それ以外の場合、$n = \tcode{nw}$とする。このとき、$0 < \delta = (\tcode{xmax} - \tcode{xmin}) / n$となる関係が満たされなければならない。 もし$nw = 0$ならば$w_0 = 1$。それ以外の場合、$k = 0, \dotsc, n - 1$に対して、$w_k = \tcode{fw}(\tcode{xmin} + k \cdot \delta + \delta / 2)$とする。`fw`は`n`回を超えて呼ばれることはない。 @@ -155,11 +155,11 @@ int roll_dice( Engine & e ) #### 簡単な説明 -区分定数分布(piecewise constant distribution)とは、区分と、区分ごとの確率を指定し、いずれかの区分の範囲の値に一様分布させる分布だ。ここで言う確率は、密度、あるいはウエイトともいう。 +区分定数分布(piecewise constant distribution)とは、区分と、区分ごとの確率を指定し、いずれかの区分の範囲の値に一様分布させる分布だ。ここでいう確率は、密度、あるいはウエイトともいう。 -ひとつの区分は`double`型の値2つ$b_i, b_{i+1}$で与える。このとき区分の乱数$x$の範囲は$[b_i, b_{i+1})$、もしくは$b_i \leq x < b_{i+1}$だ。$n$個の値を指定すると、$n-1$個の区分を指定したことになる。 +1つの区分は`double`型の値2つ$b_i, b_{i+1}$で与える。このとき区分の乱数$x$の範囲は$[b_i, b_{i+1})$、もしくは$b_i \leq x < b_{i+1}$だ。$n$個の値を指定すると、$n-1$個の区分を指定したことになる。 -例えば`{0.0, 1.0}`という2つの`double`型の値をつかって1つの区分を与えた場合、これは$0.0 \leq x < 1.0$という値の範囲の区分である。`{0.0, 1.0, 2.0}`という3つの`double`型の値は2つの区分になり、それぞれ$0.0 \leq x < 1.0$, $1.0 \leq x < 2.0$になる。 +例えば`{0.0, 1.0}`という2つの`double`型の値を使って1つの区分を与えた場合、これは$0.0 \leq x < 1.0$という値の範囲の区分である。`{0.0, 1.0, 2.0}`という3つの`double`型の値は2つの区分になり、それぞれ$0.0 \leq x < 1.0$, $1.0 \leq x < 2.0$になる。 一般に、$n$個の`double`型の値$b_0, \dotsc, b_n$で$n-1$個の区分を表現する。このとき、$b_i < b_{i+1}$が$i = 0, \dotsc, n-1$までの$i$について成り立たなければならない。つまり区分を指定する`double`型の値は、後続の値より小さくなければならないということだ。 @@ -207,11 +207,11 @@ $0 < S = w_0 + \dotsb + w_{n-1}$ #### 変数の宣言 -`std::piecewise_constant_distribution`では、`double`型の値の集合を2つ渡す必要がある。ひとつは区間を指定するための$N$個の`double`型に変換可能な値で、もう一つは区間ごとの確率を指定するための$N-1$個の`double`型に変換可能な値だ。 +`std::piecewise_constant_distribution`では、`double`型の値の集合を2つ渡す必要がある。1つは区間を指定するための$N$個の`double`型に変換可能な値で、もう1つは区間ごとの確率を指定するための$N-1$個の`double`型に変換可能な値だ。 ##### イテレーターによる指定 -イテレーターで区間と確率を指定するコンストラクターは以下の通り +イテレーターで区間と確率を指定するコンストラクターは以下のとおり。 ~~~c++ template @@ -221,12 +221,12 @@ piecewise_constant_distribution( ); ~~~ -`[firstB, lastB)`は区間を指定するための$N$個の値を参照する入力イテレーターのペアだ。`firstW`はそれぞれの区間の確率を指定する$N-1$個の値を参照する入力イテレーターの先頭だ。`lastW`がないのは、確率の個数は$N-1$個であると分かっているからだ。 +`[firstB, lastB)`は区間を指定するための$N$個の値を参照する入力イテレーターのペアだ。`firstW`はそれぞれの区間の確率を指定する$N-1$個の値を参照する入力イテレーターの先頭だ。`lastW`がないのは、確率の個数は$N-1$個であるとわかっているからだ。 もし`[firstB, lastB)`のサイズが1以下の場合、区間は`[0.0, 1.0)`になり、確率は$\frac{1}{1}$になる。 -##### 利用例 +利用例: ~~~cpp int main() @@ -244,7 +244,7 @@ int main() 区間は`[-1.0, 1.0)`と`[1.0, 2.0)`の2つ。確率はそれぞれ$\frac{1}{6}$、$\frac{5}{6}$だ。 -区間を表現する値が足りない場合は以下の通り。 +区間を表現する値が足りない場合は以下のとおり。 ~~~cpp int main() @@ -260,7 +260,7 @@ int main() ##### 初期化リストと関数オブジェクトによる指定 -初期化リストと関数を指定するコンストラクターは以下の通り。 +初期化リストと関数を指定するコンストラクターは以下のとおり。 ~~~c++ template @@ -277,7 +277,7 @@ piecewise_constant_distribution( `bl.size()`が1以下の場合、区間は`[0.0, 1.0)`になり、確率は$\frac{1}{1}$になる。 -##### 利用例 +利用例: ~~~cpp int main() @@ -294,7 +294,7 @@ int main() ##### 区間数、最小、最大、関数オブジェクトによる指定 -コンストラクターの宣言 +コンストラクターの宣言: ~~~c++ template @@ -313,7 +313,7 @@ $nw = 0$の場合、区間の個数$n$は$1$になる。それ以外の場合、 $ k = 0, \dotsc, n - 1$において、区間は$b_k = \tcode{xmin} + k \cdot \delta $ for $ k = 0, \dotsc, n$とし、確率は$w_k = \tcode{fw}(b_k + \delta / 2) $とする。 -##### 利用例 +利用例: ~~~cpp int main() @@ -367,7 +367,7 @@ int main() 区分線形分布における確率は、区間に対してではなく、内部境界に対して指定する。指定した全区間における値の出現確率は、内部境界から内部境界に向かって指定した確率の差の方向に線形に増加、もしくは減少する。 -例えば区分`{0.0, 1.0}`と確率`{1.0, 2.0}`を指定した場合、これはひとつの区間`[0.0, 1.0)`について、内部境界`0.0`の確率は$\frac{1}{3}$、内部境界`1.0`の確率は`\frac{2}{3}`とし、$0.0 \leq x < 1.0$の範囲の乱数`x`を生成する。内部境界区間の範囲に注意。`1.0`未満なので、`1.0`は出ない。 +例えば区分`{0.0, 1.0}`と確率`{1.0, 2.0}`を指定した場合、これは1つの区間`[0.0, 1.0)`について、内部境界`0.0`の確率は$\frac{1}{3}$、内部境界`1.0`の確率は`\frac{2}{3}`とし、$0.0 \leq x < 1.0$の範囲の乱数`x`を生成する。内部境界区間の範囲に注意。`1.0`未満なので、`1.0`は出ない。 そして、区間の間の値は、区間を区切る2つの内部境界の確率の差によって、線形に増加、もしくは減少する。例えば値`0.25`が出る確率は$\frac{1.25}{3}$、`0.5`が出る確率は$\frac{1.5}{3}$、値`1.75`がでる確率は$\frac{1.75}{3}$だ。 @@ -391,6 +391,8 @@ TODO: グラフ、横軸が乱数値、縦軸が確率 -+----+----+ 0.0 1.0 2.0 ~~~ +fig/fig39-01.png + #### 数学的な説明 @@ -424,9 +426,9 @@ piecewise_linear_distribution( `[firstB, lastB)`は区間、`firstW`から区間数までのイテレーターが確率。 -`firstB == lastB`もしくは`++firstB == lastB`の場合、つまり内部境界が1個以下で、空の場合、区間数はひとつで`[0.0, 1.0)`の範囲、確率は`{0.0, 1.0}`となる。 +`firstB == lastB`もしくは`++firstB == lastB`の場合、つまり内部境界が1個以下で、空の場合、区間数は1つで`[0.0, 1.0)`の範囲、確率は`{0.0, 1.0}`となる。 -##### 使い方 +使い方: ~~~cpp int main() @@ -476,7 +478,7 @@ piecewise_linear_distribution( 内部境界が1個以下の場合はイテレーターの場合と同じ。 -##### 使い方 +使い方: ~~~cpp int main() @@ -512,7 +514,7 @@ piecewise_linear_distribution( `nw`が個数、`xmin`が最小値、`xmax`が最大値、`fw`が関数オブジェクト。 -関数オブジェクト`fw`は`double`型から変換できる実引数を1つだけとり、戻り値の型は`double`型に変換できること。 +関数オブジェクト`fw`は`double`型から変換できる実引数を1つだけ取り、戻り値の型は`double`型に変換できること。 $\tcode{nw} = 0$ならば空であり、イテレーターの場合と同じ。 @@ -520,7 +522,7 @@ $\tcode{nw} = 0$ならば空であり、イテレーターの場合と同じ。 内部境界$b_k$は$k = 0, \dotsc, n$について$b_k = \tcode{xmin} + k \cdot \delta$とする。確率$w_k$は$k = 0, \dotsc, n$について$w_k = \tcode{fw}(b_k)$とする。 -##### 使い方 +使い方: ~~~cpp int main() diff --git a/400-gdb.md b/400-gdb.md index f913ec3..5a3e322 100644 --- a/400-gdb.md +++ b/400-gdb.md @@ -12,7 +12,7 @@ int main() } ~~~ -しかし実際に実行して見ると、`1`から`9`までの整数しか標準出力しない。なぜだろうか。 +しかし実際に実行してみると、`1`から`9`までの整数しか標準出力しない。なぜだろうか。 読者の中にはコード中の問題のある箇所に気が付いた人もいるだろう。これはたったの5行のコードで、問題の箇所も1箇所だ。これが数百行、数千行になり、関数やクラスを複雑に使い、問題の原因は複数の箇所のコードの実行が組み合わさった結果で、しかも自分で書いたコードなので正しく書いたはずだという先入観がある場合、たとえコードとしてはささいな間違いであったとしても、発見は難しい。 @@ -96,7 +96,7 @@ Reading symbols from program...done. (gdb) ~~~ -ここにGDBのコマンドを入力する。ヘルプを表示するコマンド`"help"`と入力してみよう。 +ここにGDBのコマンドを入力する。ヘルプを表示するコマンド`help`と入力してみよう。 ~~~ (gdb) help diff --git a/fig/fig39-01.png b/fig/fig39-01.png new file mode 100644 index 0000000..1ff11c0 Binary files /dev/null and b/fig/fig39-01.png differ