一様乱数と正規乱数
C++11からboostなくてもよくなったんで、使い方メモっておく。正規分布に設定するパラメーターは平均と"標準偏差"であって、"分散"ではない点に注意。
あと、擬似乱数生成器をあえて値渡ししてるんだけど、内部で保有しているとおもわれる乱数の状態もコピーするっぽく、乱数は"seedで指定した値のはじめから"ではなく、"続きから"出てくる点も注意する。
#include <iostream> #include <iomanip> #include <string> #include <map> #include <random> template<class T_> void show_histgram(T_ & dist, std::mt19937 engine) { //ヒストグラム生成 std::cout << "======= show histgram =========" << std::endl; std::map<int, int> hist; for (int n = 0; n < 10000; ++n){ ++hist[std::round(dist(engine))]; } for (auto p : hist) { std::cout << std::fixed << std::setprecision(1) << std::setw(2) << p.first << ' ' << std::string(p.second / 200, '*') << std::endl; } } template<class T_> void show_value(T_ & dist, std::mt19937 engine, int n) { //値表示 std::cout << "======= show values =========" << std::endl; for(int i = 0; i < n; ++i){ std::cout << dist(engine) << std::endl; } } int main() { //シードを100に固定したメルセンヌ・ツイスター乱数生成器 std::mt19937 engine(100); // 平均0, "標準偏差"2の正規分布 & 一様分布 std::normal_distribution<> normal(0, 2); std::uniform_real_distribution<> unif(-3.0, 3.0); //ヒストグラム表示 show_histgram(normal, engine); show_histgram(unif, engine); //値表示 show_value(normal, engine, 5); show_value(normal, engine, 5); }
実行結果
======= show histgram ========= -8 -7 -6 -5 -4 * -3 *** -2 ****** -1 ******** 0 ********** 1 ******** 2 ***** 3 *** 4 * 5 6 7 8 ======= show histgram ========= -3 **** -2 ******** -1 ******** 0 ******** 1 ******** 2 ******* 3 **** ======= show values ========= 1.0 4.0 -3.2 -1.3 -5.1 ======= show values ========= 1.8 1.0 4.0 -3.2 -1.3
auto使うとラムダ書きやすい
これでいいんだっていう。
#include <iostream> #include <functional> int main() { auto lambda = [](int x, int y) -> int { return x + y; }; auto f = std::bind(lambda, std::placeholders::_1, 10); std::cout << f(1) << std::endl; return 0; }
実行結果
11
Xを越える最初のコンテナの要素へのイテレーターを返す
毎回関数オブジェクト使ってたんだけどlower_boundってのがあるんだなって。
lower_boundは"以上(>=)"なんだけど、"より大きい(>)"をやるには同様にupper_boundってのがあるのか。
#include <iostream> #include <vector> #include <algorithm> int main() { //適当なデータ std::vector<double> x = { 1, 3, 5, 7, 8, 9 }; //プレディケード版 struct Pred{ Pred(double x) : x_(x){} bool operator()(double x){ return x > x_; } double x_; }; std::vector<double>::const_iterator it1 = std::find_if(x.begin(), x.end(), Pred(3.3)); std::cout << "3.3を越える最初のデータ:" << *it1 << std::endl; //lower_bound版 std::vector<double>::const_iterator it2 = std::lower_bound(x.begin(), x.end(), 3.3); std::cout << "3.3を越える最初のデータ:" << *it2 << std::endl; return 0; }
3.3を越える最初のデータ:5 3.3を越える最初のデータ:5
std::greaterとstd::lessの挙動がよくわからん
あるクラスのオブジェクトが入ったコンテナを、そのクラスのメンバーの大小に応じて、ソートしたい、そんな時、あると思います。
だけど、書き方がよくわからんかったのでメモ。クラスの外に比較用のプレディケェード作れば楽ってのは知ってるのだが、こうしたかった。
この辺の「sort比較演算子は < がデフォで > の時にはなんかある」みたいな話はどこかのC++本 or サイトで見た記憶があるのだが全く思い出せない…
そして、以下のコードはVS2013だと通るんだけど、ideoneのgcc(4.8.1)で試したらアウトだった。ぐぬぬ。
#include<iostream> #include<vector> #include <functional> #include<algorithm> //適当なクラス struct Hoge { Hoge(int x) : x_(x){} bool operator<(const Hoge & inRhs){ return x_ < inRhs.x_; } bool operator>(const Hoge & inRhs){ return !(this->operator<(inRhs.x_)); } int x_; }; int main() { //適当なデータ std::vector<Hoge> hoges; hoges.push_back(Hoge(9)); hoges.push_back(Hoge(1)); hoges.push_back(Hoge(3)); hoges.push_back(Hoge(7)); hoges.push_back(Hoge(4)); std::cout << "元のデータ" << std::endl; std::for_each(hoges.begin(), hoges.end(), [](Hoge & hoge){std::cout << hoge.x_ << std::endl; }); //↓はだめ //std::sort(hoges.begin(), hoges.end(), std::less<Hoge>()); //↓はいい //std::sort(hoges.begin(), hoges.end(), std::less<>()); //↓はいい //std::sort(hoges.begin(), hoges.end(), std::less<Hoge&>()); std::sort(hoges.begin(), hoges.end()); std::cout << "x_の昇順にソートしたデータ" << std::endl; std::for_each(hoges.begin(), hoges.end(), [](Hoge & hoge){std::cout << hoge.x_ << std::endl; }); //↓はだめ //std::sort(hoges.begin(), hoges.end(), std::greater<Hoge>()); //↓はいい //std::sort(hoges.begin(), hoges.end(), std::greater<Hoge&>()); std::sort(hoges.begin(), hoges.end(), std::greater<>()); std::cout << "x_の降順にソートしたデータ" << std::endl; std::for_each(hoges.begin(), hoges.end(), [](Hoge & hoge){std::cout << hoge.x_ << std::endl; }); return 0; }
実行結果。
元のデータ 9 1 3 7 4 x_の昇順にソートしたデータ 1 3 4 7 9 x_の降順にソートしたデータ 9 7 4 3 1
〜2014/01/31追記〜
コメント欄でアドバイスいただいたように、constメソッドになってないからだった。↓にすれば全部のコードでOKだった。
ありがとうございます!
struct Hoge { Hoge(int x) : x_(x){} bool operator<(const Hoge & inRhs) const{ return x_ < inRhs.x_; } bool operator>(const Hoge & inRhs) const{ return !(this->operator<(inRhs.x_)); } int x_; };
ダブル・ディスパッチを書いてみる
意識しないで使ってそうだが、ダブル・ディスパッチ~ 典型的なオブジェクト指向プログラミング・イディオム ~にあるダブル・ディスパチをC++でメモっておく。
これは要するにif-else or switch的な処理で書いてしまいそうな所を、あるメソッド数呼び出しの中で自身を引数として別な関数を呼び出す事で回避するテクニック。
#include<iostream> //前方宣言 class Member; class CD; class DVD; //Member系 class Member { public: virtual int calculateRentalFeeForCD(CD & item) = 0; virtual int calculateRentalFeeForDVD(DVD & item) = 0; }; class CommonMember : public Member { public: int calculateRentalFeeForCD(CD & item){return 100;} int calculateRentalFeeForDVD(DVD & item){return 300;} }; class GoldMember : public Member { public: int calculateRentalFeeForCD(CD & item){return 99;} int calculateRentalFeeForDVD(DVD & item){return 100;} }; //Item系 class Item { public: virtual int calculateRentalFee(Member & member) = 0; }; class CD : public Item { public: int calculateRentalFee(Member & member){return member.calculateRentalFeeForCD(*this);} }; class DVD : public Item { public: int calculateRentalFee(Member & member){return member.calculateRentalFeeForDVD(*this);} }; //メイン int main() { CommonMember common; GoldMember gold; CD cd; DVD dvd; std::cout << "Member:Common, Item:CD, Fee:" << cd.calculateRentalFee(common) << std::endl; std::cout << "Member:Gold, Item:CD, Fee:" << cd.calculateRentalFee(gold) << std::endl; std::cout << "Member:Common, Item:DVD, Fee:" << dvd.calculateRentalFee(common) << std::endl; std::cout << "Member:Gold, Item:DVD, Fee:" << dvd.calculateRentalFee(gold) << std::endl; return 0; }
実行結果
Member:Common, Item:CD, Fee:100 Member:Gold, Item:CD, Fee:99 Member:Common, Item:DVD, Fee:300 Member:Gold, Item:DVD, Fee:100
Boostのlibファイルのリンクは自動で行われている
vector中の特定の条件を満たす要素のインデックスだけを抽出
vector中の特定の条件を満たす要素だけを抽出 - My Life as a Mock Quantで要素自身を抜いていたけど、
これが大きいオブジェクトだったらコピーコストが凄い事にと思うと夜も眠れないので、インデックスだけ抜くようにした…ら…ば…結構めんどい書き方になった。
何方かもっといいやり方教えてください。
#include<iostream> #include<vector> #include<algorithm> #include <functional> int main() { //テストデータ std::vector<int> x,y; x.push_back(1); x.push_back(3); x.push_back(4); x.push_back(5); x.push_back(3); //条件用Functor struct IsNotThree : public std::unary_function<int, bool> { bool operator()(int x) const{return x!=3;} }; //インデックス抽出 std::vector<int>::iterator it = std::find_if(x.begin(), x.end(), IsNotThree()); while (it != x.end()) { y.push_back(std::distance(x.begin(), it)); it = std::find_if(++it, x.end(), IsNotThree()); } //表示 struct Show{void operator()(int x){std::cout << x << std::endl;}}; std::for_each(y.begin(), y.end(), Show()); return 0; }
実行結果
0 2 3