カテゴリ:C++プログラミング の記事一覧

|

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
スポンサー広告 | --/--/-- --:--

const 修飾子の二重の意義

プログラミング関係は、完全に素人なので、つぶやき程度です。

C++ で関数の引数に const 修飾子をつける時の意義って、
考えてみると意外に深いです。

参照渡しの引数につける場合。

たとえば、Matrix という行列を扱うクラスがあったとして、
そのオブジェクト A の参照を渡して、その行列式を返す関数。

double det (const Matrix& A);


行列の場合、データが膨大になるので、コピーして値渡しするよりは、
参照渡しの方が効率的。
この時、行列式を計算して値を返すだけなので、
行列の中身は変更しないということを const で保証しています。

このように定義することで、関数を呼び出す時に、
勝手に内容を変更される心配がなく、呼び出し側が安心して使える
という意義がありますね。

では、値渡しの場合はどうでしょう?

たとえば、2つのdouble型の数を比較して、大きい方を返す関数。

double max ( const double a, const double b);


上記の意義だけだと、値渡しに const をつけても、
何の意義もないということになります。
なぜなら、値渡しの場合は、関数内では値だけコピーして使用するのだから、
呼び出した側の内容が変更されようがありませんよね。

しかし、それでも意義はあるように思います。
呼び出し元の内容を変更する心配はないにせよ、
実際に大小比較する前に、うっかり間違えて変更してしまったら、
この関数自体が機能しません。

const をつけることによって、うっかり変更してしまった場合には
コンパイルエラーが発生するため、バグを防げるという効果があると思います。
つまり、関数を正しく機能させるために、プログラムミスで変更してしまうのを防ぐ
という意義がありますね。

たとえるならば、参照渡しの場合は、

(1) 社外から貴重な資料を預かってきているので、
それを絶対に汚してはいけない

(2) 社内的にも汚してしまったら、
調べたかった情報が得られないので、
絶対に汚してはいけない

という2重の意義があることになります。

値渡しの場合は、
資料はコピーしてすぐにお返しするので、第一の意義はないのですが、
それでも第二の意義はあるということになります。

あくまでも素人考えです。
スポンサーサイト
C++プログラミング | コメント(0) | 2015/08/13 00:06

数値計算プログラミング

以前の記事で書いたように、日頃実験データの解析や簡単な数値計算などには、
Wave Metrics 社の Igor Pro というソフトを使用しています。

このソフト、グラフ描画や数値解析機能には申し分ないのですが、
内部の専用プログラミング言語が劣悪すぎて、
プログラミングにストレスがたまりまくるんです。

計算の時は、このソフトを使わずに、C++で書くこともあるのですが、
できれば、計算途中にリアルタイムでグラフ表示をさせたんですよね。

その Igor というソフトにも別売りでC++とのインターフェースも存在するようなのですが、
その使用サンプルを眺めてみると、かなりめんどくさそう・・・
それならば、いっそのこと、C++でグラフ表示まで自作するか、
既存のグラフ描画ライブラリーを使用するか・・・
ということで、NPlot というライブラリーを使ってみようかなというのが前回の話でした。

で、グラフ描画の話はさておいて、
この Igor のデータ構造、非常に使い勝手がいいんです。

実際の数値データを扱うのですから、通常、1次元配列のようなものになりますが、
Igor の場合、それに加えて個々のデータが独自の横軸(X軸)情報を保有しているんです。

考えてみれば、自然科学ではほとんどのデータに横軸が存在してるんですよね。
たとえば、オシロスコープで取った波形では、横軸は時間ですし、
I-V特性のようなデータは、横軸が電圧ですね。
横軸の存在しないデータといえば、クラス50人分の身長データのような
統計的サンプルぐらいしか思い浮かびません。

Excel などを使っていると、通常、グラフにするとき、
横軸と縦軸の2本のデータ配列を使って、XYプロットをすると思います。
でも、横軸というのはたいていの場合、等間隔で並んだ数値列になっているだけなんですよね。

たとえば、オシロで取った波形を考えると、横軸は等間隔に並んだ時刻の羅列です。
結局、有意な情報は最初(画面左端)の時刻と最後(画面右端)の時刻だけです。
あるいは、最初の時刻と刻み間隔(○s/divの値)でもいいかもしれません。

要は電圧の値の時間変化の1次元配列に、
この最初と最後の時刻情報だけ追加しておけば、事足りるんですね。

個々のデータにこの横軸情報をインクルードしておけば、
XYプロットのように、2つのデータの紐づけをいちいち管理しなくても、
個々のデータを個別に管理するだけでよいというわけです。

たとえば、こちらは Igor のグラフプロットの例ですが、
Igor-wave-02.png
赤い方のデータは、[0,10]、青い方のデータは[-5,5]という横軸情報を独自に持っているので、
2本のデータをプロットするだけで、しかるべき横軸の場所にプロットされます。

また、データ自身が横軸を持っているので、
微分や積分やフーリエ変換など、横軸を必要とする演算はすべて、
そのデータに付属するメソッドとして、インプリメントできます。

というわけで、話が長くなりましたが、
自作ライブラリを作るうえで、このデータ構造を採用したいと思うのです。

つまり、データ配列に加えて、横軸情報を追加したものをクラスとして定義してやって、
そこに微分、積分、フーリエ変換などの演算をメソッドとして追加する
というイメージを考えています。
配列間における四則演算なども演算子の多重定義で実現したいですね。

Igor では、このデータ構造を「ウェーブ」と呼んでいるので、
double型(実数)のデータ配列に対して、 DWave というクラスでカプセル化して、

DWave d1, d2, d3;
・・・
d1 = 0; //すべての要素に 0 を入れる
d1.SetScale(-100,100); //横軸を [-100,100]に設定
・・・
double x = d2.Integrate(-1,1); //d2 を [-1,1]で積分して、x に入れる
d3 = d1 + d2;   //すべての要素で、d3[i] = d1[i] + d2[i]
・・・

というような感じで扱えるようにできれば・・・と思っています。

実は以前から作成していて、もうほとんど完成して実際に使っているのですが・・・
もう一度見直してみて、改良しながら、ここに記録していきたいなと思います。

ちなみに、僕はプログラミングはド素人なので、
かなり我流で危なげでプログラミングをしていると思いますが、
その点は、ご容赦ください^^;
ジャンル:[学問・文化・芸術]  テーマ:[自然科学
C++プログラミング | コメント(0) | 2014/06/06 12:22

グラフ描画

仕事では、実験屋といえども、
時には実験装置の設計や実験結果の考察のために、
数値計算をしたりもします。
(もともとそっちの方が好きだったりするのですが・・・)

C++が好きなので、C++で計算させて、結果をテキスト形式で出力して、
Wave Metrics社の「Igor Pro」というグラフソフトで表示する。
ということをやっていたのですが、
いちいち、結果をソフトに持っていくのがめんどくさい!

というわけで、実は、このIgor Proというソフトは、単なるグラフ描画ソフトではなく、
数値解析ソフトで、統計解析から微分・積分・フーリエ変換・行列計算など
かなりいろんな数学的計算が可能なので、内部でプログラミングもできるので、
最近は、このソフトの内部でプログラミングをして計算していました。

ところが、このプログラミング言語が問題で、
いまいち、というかかなり使いにくいのです!

特に、C++に慣れてしまった人間にとっては、
オブジェクト指向に対応してないと、かなりきついです。
それどころか、参照渡しができなかったり、
グローバルな名前の衝突を気にしなければいけなかったり・・・とか、
まあ、数え上げたらきりがないのですが(笑)

う~ん、数値解析機能としては申し分ないんですけど、
もったいない限りです。

というわけで、前置きが長くなりましたが・・・
C++からアクセスできるグラフ描画ライブラリ
欲しいなと思っているわけです。
そうすれば、計算しながらリアルタイムで表示できますからね。

自作するのも面白いなあと思っているのですが、
(実際に以前に、VisualC++のMFCを使って作りかけていた残骸があるのですが)
とりあえず、既存のものでないか探してみたら、NPlotなるものがあるようですね。

で、さっそく、このライブラリをダウンロードして、
参考文献[1]のブログ記事を参考にさせていただきながら、
.NET CLRのWindowsフォームアプリで記述してみたら、
こんな感じにうまくいきました。

NPlotTest01.jpg

とりあえず、これを使うのも一案ですね!

プログラムは、参考文献のものとほとんど同じですが、
MainFormのコンストラクターのところに、
以下の数行を書き込んだだけです。

----------------------------------------------
ArrayList^ data = gcnew ArrayList();

data->Add(1);
data->Add(5);
data->Add(3);
data->Add(-2);
data->Add(0.5);

NPlot::LinePlot^ lp = gcnew NPlot::LinePlot(data);

this->plotSurface2D1->Add(lp);
this->plotSurface2D1->Refresh();
------------------------------------------------------

ちょっとプログラミング熱が上がってるので、
自分用にカスタマイズしたものを自作するのも楽しそうですね。

「プログラミング」というカテゴリを作ったので、
引き続き、進捗状況を報告していきます。


参考文献
[1] ひよっこ女性SEの記録
  「フリーのライブラリNplotを使ってグラフを描く」
  http://ameblo.jp/se-natsu/entry-10151086471.html
C++プログラミング | コメント(2) | 2013/11/26 19:13
 | HOME | 

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。