goo blog サービス終了のお知らせ 

Java エクセルVBAのサンプル

浮かんだ、JavaとVBAのサンプルを備忘録として、残しておこうかな、
コードを利用するときは自己責任にてよろしく

複素行列の逆行列と行列の積で、交流回路の基本的な計算

2009-01-26 08:02:24 | Weblog

前々日と前日に複素数の逆行列と行列の積の関数をエクセルのVBAで書いてみた。
では、その応用は??ということで、電気の交流回路の基本的な計算を
行なってみた。キルヒホッフの法則で、連立方程式を立ててみました。


図5


エクセルでの計算結果

図7

エクセルでの計算結果


図8

エクセルでの計算結果


回路図は、同じでないが、基本的に全部同様な連立方程式を解いているだけです。
一度フォームを作ると、データを入れ替えるだけで、次々に
連立方程式を解くことが出来ます。


複素行列の掛け算

2009-01-25 08:50:04 | Weblog

前日に複素行列の逆行列を作ってみましたが、
これだけでは、不便なのです。
複素行列の掛け算があると便利です。
足し算とマイナス関数は、前日の複素数の逆行列に含まれています。
以上のアイテムを利用して、複素行列の掛け算を
作ってみました。

(a+bi)(c+di)=ac-bd+(ad+bc)i

となり、二つの複素数のa,b,c,dを求めれば、後は、エクセルの
行列の積を利用すれば良い事がわかります。

Public Function IMMult(aa As Variant, bb As Variant) As Variant

    Dim a As Variant, b As Variant
    Dim ra() As Double, ia() As Double, rb() As Double, ib() As Double
    Dim la1 As Integer, ua1 As Integer, la2 As Integer, ua2 As Integer
    Dim lb1 As Integer, ub1 As Integer, lb2 As Integer, ub2 As Integer
    Dim i As Integer, j As Integer
    Dim rr As Variant, ii As Variant
    Dim ccc As Variant

    a = aa
    b = bb

 
        la1 = LBound(a, 1)
        ua1 = UBound(a, 1)

        la2 = LBound(a, 2)
        ua2 = UBound(a, 2)

        lb1 = LBound(b, 1)
        ub1 = UBound(b, 1)

        lb2 = LBound(b, 2)
        ub2 = UBound(b, 2)


    ReDim ra(la1 To ua1, la2 To ua2), ia(la1 To ua1, la2 To ua2)
    ReDim rb(lb1 To ub1, lb2 To ub2), ib(lb1 To ub1, lb2 To ub2)

        For i = la1 To ua1
            For j = la2 To ua2
                ra(i, j) = ImReal(a(i, j))
                ia(i, j) = Imaginary(a(i, j))
            Next
        Next
     
        For i = lb1 To ub1
            For j = lb2 To ub2
                rb(i, j) = ImReal(b(i, j))
                ib(i, j) = Imaginary(b(i, j))
            Next
        Next
  
    rr = add(WorksheetFunction.MMult(ra, rb), negamtrix(WorksheetFunction.MMult(ia, ib)))
    ii = add(WorksheetFunction.MMult(ia, rb), WorksheetFunction.MMult(ra, ib))


        la1 = LBound(rr, 1)
        ua1 = UBound(rr, 1)

        la2 = LBound(rr, 2)
        ua2 = UBound(rr, 2)

    ReDim ccc(la1 To ua1, la2 To ua2)

        For i = la1 To ua1
            For j = la2 To ua2
                ccc(i, j) = Complex(rr(i, j), ii(i, j))
            Next
        Next
 
    IMMult = ccc


End Function

以上が、複素行列の積になります。前日の逆行列を求めるときに使った
関数も使っているで、前日のソースに今回のソースを足して使ってみてください。
これも、配列変数を使っているので、shift+ctrl,リターンをお忘れなく

複素数の逆行列

2009-01-24 14:12:18 | Weblog

まず、エクセルで、複素数を扱えるようにアドインと参照設定をしておくことを
お忘れなく、




複素行列(a+bi)に、この逆行列(c+di)を掛け合わせると単位行列Eになることを
応用する
左辺を展開して、整理する



複素数の性質より、ac-bdは、単位行列に、ad+bcは、ゼロ行列になる。











aとbから、cが求められ、cとa,bからdが求まる。
これで、複素数の逆行列を計算できる。
エクセルに行列の掛け算、逆行列の関数はあるが、
今回は、行列の足し算と、マイナスにする処理がないので、加えた

まず、行列の足し算の関数を作ってみた

Public Function add(a As Variant, b As Variant) As Variant

    Dim i As Integer, j As Integer
    Dim aad As Variant

    aad = a

        For i = LBound(aad, 1) To UBound(aad, 1)
            For j = LBound(aad, 2) To UBound(aad, 2)
                aad(i, j) = aad(i, j) + b(i, j)
            Next
        Next
 
    add = aad
  
End Function

次にマイナスにする行列の関数を作った

Public Function negamtrix(a As Variant) As Variant

    Dim i As Integer, j As Integer
    Dim aa As Variant

    aa = a

        For i = LBound(aa, 1) To UBound(aa, 1)
            For j = LBound(aa, 2) To UBound(aa, 2)
                aa(i, j) = aa(i, j) * -1
            Next
         Next
 
    negamtrix = aa
 
End Function

ここで、a+biの逆行列,c+diの引数a、bが、まず与えられているとすると
cとdは以下の関数で計算される

Public Function cc(a As Variant, b As Variant) As Variant

    Dim c As Variant

        c = WorksheetFunction.MMult(b, WorksheetFunction.MInverse(a))
        c = WorksheetFunction.MMult(c, b)
        c = add(a, c)
        c = WorksheetFunction.MInverse(c)

    cc = c

End Function

Public Function dd(a As Variant, b As Variant) As Variant

    Dim d As Variant, c As Variant

    c = cc(a, b)

        d = WorksheetFunction.MMult(WorksheetFunction.MInverse(a), b)
        d = WorksheetFunction.MMult(d, c)
        d = negamtrix(d)

    dd = d

End Function

実部と虚部の配列を、複素数の配列に変換するプログラムは

Public Function complexdim(a As Variant, b As Variant) As Variant

    Dim i As Integer, j As Integer
    Dim l As Integer, u As Integer
    Dim complexdi As Variant

        l = LBound(a, 1)
        u = UBound(a, 1)

    ReDim complexdi(l To u, l To u)


        For i = LBound(a, 1) To UBound(a, 1)
            For j = LBound(a, 2) To UBound(a, 2)
    
                complexdi(i, j) = Complex(a(i, j), b(i, j))
            
            Next
      
        Next

    complexdim = complexdi


End Function

以上の複素数a+biの実部a、虚部bから、逆行列c+diのcである実部とdである虚部を求め
逆行列の複素配列complexdimを求めた形になる。
以上の関数を作っておくと、逆行列の関数は、以下のようにシンプルな形になる。

Public Function IMinverse(a As Variant, b As Variant) As Variant

    IMinverse = complexdim(cc(a, b), dd(a, b))

End Function

a+biの実部と虚部から、逆行列の実部c、虚部dを求めその複素配列に変換して
ワークシートに返す関数になります。

次に、a+biの複素配列を実部行列aと虚部行列bに分解しないといけない
逆行列のプログラムは、以下のように書いてみた。

Public Function cIMinverse(a As Variant) As Variant

    Dim aa As Variant
    Dim la1 As Integer, ua1 As Integer, la2 As Integer, ua2 As Integer
    Dim rr As Variant, ii As Variant
    Dim i As Integer, j As Integer

    aa = a

        la1 = LBound(aa, 1)
        ua1 = UBound(aa, 1)

        la2 = LBound(aa, 2)
        ua2 = UBound(aa, 2)

    ReDim rr(la1 To ua1, la2 To ua2), ii(la1 To ua1, la2 To ua2)

        For i = la1 To ua1
            For j = la2 To ua2
                rr(i, j) = ImReal(aa(i, j))
                ii(i, j) = Imaginary(aa(i, j))
            Next
        Next

    cIMinverse = IMinverse(rr, ii)

End Function

以上で、エクセルのワークシート上での、複素数の逆行列の関数が出来たと思います。
注意点)このプログラム、a+bi行列のaに逆行列が存在ないと
関数はエラーになります。

計算結果例は、以下のようになりました。



計算結果は、配列変数で返ってきているので、shift+ctrlで、リターンをお忘れなく





統計、正規分布の母集団からサンプルの正規分布

2009-01-20 19:22:04 | Weblog
正規分布(μ,σ^2)の母集団から
サンプリングしてサンプルの分布は、(μ,σ^2/n)になるというのを
よく解らず、悩んでいたのですが、
やっと、シュミレートするエクセルVBAを書いて、結果を確認できる様になった。
方法は、まず、母集団の生成、、

平均値5、標準偏差10の正規分布の10000個の乱数を発生させる。
もともと乱数なので、最初から10点、次の10点と、10点間隔で、サンプリングした
数字を配列に入れ、平均値を算出して、1000個のサンプリングの平均値を算出する
この1000個のサンプリングしたデータ集団が、平均値μ、分散値σ^2/nになっていれば
良いはずなので、サンプリングしたデータの平均値は、5、標準偏差が3.16227766016838
になっていれば良いことなのですね。

まず10000個の母集団の発生

Public Sub seiki()

Dim i As Integer

    '乱数発生数
    For i = 1 To 10000
        '平均5、標準偏差10の乱数
        Cells(i, 1).Value = WorksheetFunction.NormInv(Rnd, 5, 10)
    Next
    

End Sub

10点ごとに、その平均値を算出、平均値の平均と、標準偏差を算出


Public Sub f()

Dim d(1 To 1000) As Variant
Dim dn(1 To 10) As Variant
Dim i As Integer, ii As Integer

    For i = 1 To 1000
        For ii = 1 To 10
        dn(ii) = Cells((i - 1) * 10 + ii, 1)
        Next
    d(i) = WorksheetFunction.Average(dn)
    Next
 
 Debug.Print WorksheetFunction.Average(d)
 Debug.Print WorksheetFunction.StDevP(d)
 Debug.Print 10# / Sqr(10)
 
End Sub

計算結果の一例

5.18770502984403
2.98938754981573
3.16227766016838

サンプル集団の分布の標準偏差は、2.989になった。
また、母集団から推定された標準偏差は3.162になった。
平均値、標準偏差も、大体同様な値になった。

プログラム一部修正 1/21日




今日の雑感

2009-01-19 14:15:05 | Weblog
エクセルのエンジニアリング関数あまり、インターネットに
応用例がないなと、特にVBAでの利用、、、、
複素数など、VBAでは、応用例が、ヒットしない。
キーワードが良くないのかな、基本的な利用は、
あるのですが、応用例が、見つからない。
複素数で、電気回路の計算など、便利だと思うですが、
書籍とか、ウェブには、応用例が少ないです。

ところで、久しぶりに書籍を「エクセル 化学」のキーワードで
検索してみたら、

Excelで解く配管とポンプの流れ
http://www.7andy.jp/books/detail/-/accd/32126215


という本がヒットした。タイトルからして、
ちょっと興味を持ったが、私の住むところでは、
立ち読みは、出来ないものだなと、残念。
買えばいいのだが、懐が寒い。困ったものだ。
プログラミングは、なかなか、出来ず、
webで、興味のあったことに出会った。雑感を書くのが
今のところ、精一杯です。



Java 重複しない乱数の作り方

2009-01-17 19:45:21 | Weblog

0~9の整数で、重複しない乱数を発生したい場合の一例として、
最初から、0~9の数字を配列に入れておいて
その配列をシャッフルする方法がある。

        //配列
        List<Integer> l = new ArrayList<Integer>();
        //配列に数字を代入
        for(int i=0;i<10;++i){
            l.add(i);
        }
        //まず、シャッフル前に配列内を表示
        StringBuffer sb = new StringBuffer();
        for(int i=0;i<10;++i){
            sb.append(l.get(i));
        }
        System.out.println(sb.toString());
        sb.delete(0, sb.length());
        //5回シャッフルする
        for(int ii=0;ii<5;++ii){
            //シャッフル
            Collections.shuffle(l);
        for(int i=0;i<10;++i){
            sb.append(l.get(i));
        }
       //シャッフル後の数字を表示
        System.out.println(sb.toString());
        sb.delete(0, sb.length());
        }


実行結果

0123456789
8721953046
6139052478
8196742305
9305286471
9826374501


このようにすれば、0~9の重複しない乱数配列を作れます。









エクセルVBAで、正規分布の乱数発生

2009-01-17 14:53:33 | Weblog
Javaでの、正規分布の乱数発生について前回書いたのですが。

エクセルでは、もっと簡単です。ワークシート上で書くのも
簡単なのですが。一度に、大量に発生させたいので、
以下のようなVBAをコーディングした。

Public Sub seiki()

Dim i As Integer

    '乱数発生数
    For i = 1 To 10000
        '平均0、標準偏差1の乱数
        Cells(i, 1).Value = WorksheetFunction.NormInv(Rnd, 0, 1)
    Next
    

End Sub

100個と10000個を発生させて、エクセルの分析ツールのヒストグラムで、
ヒストグラムを作り。どの程度の奇麗な正規分布になるか、、
計算し見て結果の図を入れていました。

100個



1000個



当然のことながら、乱数の数が多いほうが
奇麗な正規分布になった。












Java 正規分布の乱数

2009-01-17 14:00:25 | Weblog


正規分布の乱数、私的には、あまり使ったのとないのですが。
結構、ネットには、転がっている。

Javaの標準APIには、平均が、0、標準偏差が 1になる
クラス Randomに、メッソド、double nextGaussian()
がある。

この利用については、以下のURLを見ると詳しく書いてある。

http://sourceforge.jp/projects/fmu/wiki/%E6%AD%A3%E8%A6%8F%E5%88%86%E5%B8%83%EF%BC%88%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%82%B5%E3%82%A4%E3%82%BA%EF%BC%89
しかし、例えば平均が、3で、標準偏差10の場合の正規分布の乱数は
どうやって作るのか???
数学を御存じの方は、いろんな正規分布は、平均値と標準偏差で
正規化すると、平均値が0で、標準偏差1の正規分布になることを
知っている。
つまり、平均値0、標準偏差1の乱数に
正規化の逆をすれば、いろいろな、正規分布の
乱数を作れることがわかる。コーディングも簡単ので、
省略するが。

世の中、とことん便利さを追求しているのか
Jakarta Commons MathのClass RandomDataImplには
平均値と分散値を指定して、乱数を発生できるも出来る。
メッソドは
public double nextGaussian(double mu,double sigma)
が存在する。
このアルゴリズムは、解らないが
容易に、希望する正規分布の乱数を作ることが出来る

今日の雑感

2009-01-14 19:53:25 | Weblog
なかなか、プログラミングも、、
プログラムするものを見つけないと、時間だけが流れます
プログラムより、ソフトウェアーの基本となる
学習が進まない。

Goo教えてなどを、見ていると、ほ、こんな事もあるのかと、
教えられることも多い。

今日気が付いたのは、逐次反応である。
化学反応の速度を表す式、、、、A~Bに変化し、B~Cに変化する
こんな一次の反応など、どんな化学物質があるのかなと
ふと疑問になっていた。

http://oshiete1.goo.ne.jp/qa4625479.html?ans_count_asc=20
この質問と、回答を見ていて、実際このような反応は
ある物かなと、疑問に思っていた。

しかし、着目点を変えると、放射性物質の放射平衡と
同様な、連立微分方程式を解いていた。

http://www.geocities.jp/tomtomf/laplace/laplace.htm
放射平衡の式を見ていると、化学反応の逐次反応と
同じではないか。

へーーーーーー、、、自然に起きる現象は、似たようなものに
なるのですね。

放射性物質の放射平衡を化学と見るか、物理と見るか、
私的には、解りませんが。
いろいろなことが、関連しているのだなと思いました。


今日の雑感

2009-01-13 13:55:52 | Weblog
ネットワークのプログラム確認用に、win98の古いパソコンを所有している。
たまにしか、電源を入れないが、いままで、もったいないので、
ウィルスソフトを入れていなかった。
ウィルスバスターを、常用のパソコンには、入れているが
win98は、サポート外。
そこで、以下のURLから、フリーのウィルスソフトを入れてみた。

http://www.kingsoft.jp/is/

取りあえず、インストールしたら、
なんと、サーバのMySQLが、フリーソフトを入れた、パソコンでは、認識しなくなった。
困ってしまって、フリーのウィルスソフトを、いろいろいじってみたが
解消できず、ファイヤーウォールを落としても、動作せず、
アンインストールかと、取りあえず、ウィルスチェックしてからと思い、、
ウィルスチェックを完了させた。
ところが、好転、ウィルスチェックを完了させた後、
サーバのMySQLにアクセスしてみたら、動いた!!!!!!
こんなこともあるんだ。
はたして、ウィルスチェックのお陰で、動作したかどうかわからないが
試してみる価値はあるかと思います。