2009-06-30[n年前へ]
■有限要素法を理解するには、プログラムリストが最も適切な表現手段である 
 20年前に出版された(今ではミステリ作家として有名な)森博嗣
 20年前に出版された(今ではミステリ作家として有名な)森博嗣の「C言語による有限要素法入門
」から。(ちなみに森博嗣
には「C言語によるマトリックス演算
」という著書もある)
本書は、有限要素法をC言語で実行することはもちろんだが、むしろ、C言語によって有限要素法を理解する目的に適している。有限要素法を理解するには、プログラムリストが最も適切な表現手段であるからであり、C言語のリストは、目に優しい端正なコーディングが可能である。
1989年1月 森博嗣
2009-12-09[n年前へ]
■エクセルの計算ワークシートをRubyでC言語に変換してみよう 
この記事のスクリプトや、(下記のエクセルファイルとは違いますが、より有用そうな)エクセルファイル例、そして、そのエクセルファイルを変換したC言語ソースを保存し、また、つらつら考えことなどを「続 エクセルの計算ワークシートをRubyでC言語に変換してみよう」 に書きましたので、下記記事を読んだ後には、上記記事(さらにその後に続く記事など)を引き続きご覧ください。
 先日、「エクセルの計算ワークシートをRuby計算スクリプトに変換してみよう」でエクセルで作った離散化シミュレーション用.xlsシートをRuby Script(プログラム)に自動的に変換する、Rubyスクリプトを作ってみました。基本的には四則演算で(反復収束計算手法を用いることにより)「この世界を(エクセル上で)シミュレーションするスプレッドシート」を作ったなら、それを他のプログラミング言語に「変換する」アプリケーション例として、エクセルのシートをRuby言語に変換するソフトを作ってみたわけです。目標は「何だかすげー!、けど、役に立たねー!」です。
 先日、「エクセルの計算ワークシートをRuby計算スクリプトに変換してみよう」でエクセルで作った離散化シミュレーション用.xlsシートをRuby Script(プログラム)に自動的に変換する、Rubyスクリプトを作ってみました。基本的には四則演算で(反復収束計算手法を用いることにより)「この世界を(エクセル上で)シミュレーションするスプレッドシート」を作ったなら、それを他のプログラミング言語に「変換する」アプリケーション例として、エクセルのシートをRuby言語に変換するソフトを作ってみたわけです。目標は「何だかすげー!、けど、役に立たねー!」です。
というわけで、引き続き、今日はエクセルのシートをC言語に変換するRubyスクリプトを書いてみました。もちろん、今回も、基本的には四則演算と数値だけで作られ、反復収束計算手法を用いることで最終的な計算結果を得るような「シート」を前提にしています。
というわけで、書いたコード"xls2c.rb"はこんな具合です。
require 'win32ole'
def getAbsolutePath(filename)
  fso=WIN32OLE.new('Scripting.FileSystemObject')
  fso.GetAbsolutePathName(filename)
end
def getAlphabet(n)
  val=n.to_f/25.0 
  mod=n%25
  result=''
  result+=('A'..'Z').to_a[(n-val)/25] if val>1
  result+=('A'..'Z').to_a[mod]
end
def defFunc(state,book)
  src=''
  book.Worksheets.each do |sheet|
    y=1
    sheet.UsedRange.Rows.each do |row|
      x=0
      record=[]
      row.Columns.each do |cell|
        if state==:def &&cell.Value.to_s!=''
          record<<'  float '+getAlphabet(x)+y.to_s+'=0.;'
        end
        if state==:init &&cell.Value!=''
record<<'  '+getAlphabet(x)+y.to_s+
            '='+cell.Value.to_s+';' if cell.Value.to_s!=''
        end
        if state==:calc &&cell.Formula!=''
t=cell.Formula.sub(/[=$]/,'')
record<<'  '+getAlphabet(x)+y.to_s+'='+t+';'
        end
        x+=1
      end
      if record.join('').gsub("\n",'')!=''
        src+=record.join("\n")+"\n" 
      end
      y+=1
    end
  end
  return src
end
filename=getAbsolutePath(ARGV[0])
excel=WIN32OLE.new('Excel.Application')
book=excel.Workbooks.Open(filename)
defsrc=defFunc(:def,book)
initsrc=defFunc(:init,book)
calcsrc=defFunc(:calc,book)
book.close
excel.quit
GC.start
puts <<INIT
// autocreated C source from excel file
// jun hirabayashi jun@irax.net http://www.hirax.net
#include "stdio.h"
// gloval variables
#{defsrc}
void init(void){
#{initsrc}}
void calc(void){
#{calcsrc}}
int main(){
  int i;
  init();
  for(i=0;i<10;i++){ calc(); }
  printf("C2=%f",C2);
  return 0;
}
INIT
 このスクリプトを、
ruby xls2c.rb ex.xls > sample.cという具合に実行すると、下のようなC言語ソースができあがります。
// autocreated C source from excel file
// jun hirabayashi jun@irax.net http://www.hirax.net
#include "stdio.h"
// gloval variables
  float A1=0.;
  float B1=0.;
  float C1=0.;
  float A2=0.;
  float B2=0.;
  float C2=0.;
  float A3=0.;
  float B3=0.;
  float C3=0.;
void init(void){
  A1=1.0;
  B1=2.0;
  C1=3.0;
  A2=1.0;
  B2=2.0;
  C2=5.0;
  A3=1.0;
  B3=2.0;
  C3=3.0;
}
void calc(void){
  A1=1;
  B1=2;
  C1=3;
  A2=1;
  B2=2;
  C2=B2+C1;
  A3=1;
  B3=2;
  C3=3;
}
int main(){
  int i;
  init();
  for(i=0;i<10;i++){ calc(); }
  printf("C2=%f",C2);
  return 0;
}
 もちろん、今回もスプレッドシートの「セル」はすべてグローバル変数として取り扱い、エクセルが最初に行う初期化ルーチンを"init"関数として定義(作成)し、次に行う反復計算を"calc"関数として定義(作成)し、それを(適当に決めた)for文で10回繰り返す(計算を収束させるためには、実際にはもっと多く繰り返し計算をさせることが必要でしょう)、というソースです。
 もちろん、今回もスプレッドシートの「セル」はすべてグローバル変数として取り扱い、エクセルが最初に行う初期化ルーチンを"init"関数として定義(作成)し、次に行う反復計算を"calc"関数として定義(作成)し、それを(適当に決めた)for文で10回繰り返す(計算を収束させるためには、実際にはもっと多く繰り返し計算をさせることが必要でしょう)、というソースです。
さて、このC言語ソースは、(たとえば、Borland C++ Compilerを使うなら)
bcc32 sample.cという具合で、sample.exeというバイナリができあがります。
いつか、エクセルのシートを変換し・作成したC言語プログラムをコンパイルすると、どれだけ遅くなるのか・どれだけ早くなるのかを、色々な環境で確かめてみたい、と思っています。
2009-12-14[n年前へ]
■続 エクセルの計算ワークシートをRubyでC言語に変換してみよう 
 前回、「エクセルの計算ワークシートをRubyでC言語に変換してみよう」でサンプルに作ったエクセルのシートが反復収束計算をする必要がない(自己参照型のシートになっていなかったこと)に気づいたので、今日はエクセル・シートを作り直し、サーバ内に置いておきましたここに置いておきます。置いたエクセル・ファイル"ex2.xls"は、5×5のセルの周囲と中央のセルが固定条件で、それ以外の(5×5内の)セルが自分の上下左右のセルの平均の値をとるというラプラス方程式を差分化したエクセルシートです。そして、xls2c.rbがエクセル・ファイルをC言語ソースに変換するRubyスクリプトで、ex2.xlsをC言語に変換した結果ファイルが、ex2.cになります。
 前回、「エクセルの計算ワークシートをRubyでC言語に変換してみよう」でサンプルに作ったエクセルのシートが反復収束計算をする必要がない(自己参照型のシートになっていなかったこと)に気づいたので、今日はエクセル・シートを作り直し、サーバ内に置いておきましたここに置いておきます。置いたエクセル・ファイル"ex2.xls"は、5×5のセルの周囲と中央のセルが固定条件で、それ以外の(5×5内の)セルが自分の上下左右のセルの平均の値をとるというラプラス方程式を差分化したエクセルシートです。そして、xls2c.rbがエクセル・ファイルをC言語ソースに変換するRubyスクリプトで、ex2.xlsをC言語に変換した結果ファイルが、ex2.cになります。
 元々の記事は、「とても無意味なこと・けれど技術発想的には何だか(的外れ具合が)面白いこと」をしよう、という考えのもとにやってみたのですが、非定常熱伝導計算の復習をしているうちに、非定常問題を解くシートに対しては、意外に使えるかもしれない、という気がしてきました。
 元々の記事は、「とても無意味なこと・けれど技術発想的には何だか(的外れ具合が)面白いこと」をしよう、という考えのもとにやってみたのですが、非定常熱伝導計算の復習をしているうちに、非定常問題を解くシートに対しては、意外に使えるかもしれない、という気がしてきました。
プログラムというものをまったく知らない人が、熱伝導方程式の物理的な意味を理解上で、表計算でシミュレーションをしてみた(習ってみた)あとに、(エクセルのセルと直感的に対応した)自動出力したC言語ソースをもとに「printfの使い方だけを習い」色んな計算をしてみれば、そして注目するセル=箇所の時間変化・経過を出力させてみたりすれば、案外面白く感じるかもしれない・・・という風にも思ったのです。
 もちろん、こんな単純自動変換Cソースでは一瞬のうちに物足りなくなるはずなので、上のような時間を経ることで、プログラム言語を学ぼうとするまでの小さな「足がかり」「キッカケ」になるのではないか、という間違っていそうなそんなことをふと思ったのです。いわば、エクセルを入口に差分化シミュレーション・プログラムの世界に"Hello World"する、というわけです。ゼロから学ぶのと、何か叩き台があって、それをほんの少しづついじりながら学ぶのとでは、気楽さが全然違うのではないか、といったことを「後付けで」考えてみたりしたのです。
 もちろん、こんな単純自動変換Cソースでは一瞬のうちに物足りなくなるはずなので、上のような時間を経ることで、プログラム言語を学ぼうとするまでの小さな「足がかり」「キッカケ」になるのではないか、という間違っていそうなそんなことをふと思ったのです。いわば、エクセルを入口に差分化シミュレーション・プログラムの世界に"Hello World"する、というわけです。ゼロから学ぶのと、何か叩き台があって、それをほんの少しづついじりながら学ぶのとでは、気楽さが全然違うのではないか、といったことを「後付けで」考えてみたりしたのです。
ちなみに、エクセルシート→C言語 変換などで、配列を使わずにグローバル変数を使ったのは、まずは何より簡単な変換スクリプトにしたいということ、そして、変換後のC言語ソースをコンパイルしたときに、少しは早く動作すると良いなと考えて、そんな作りにしてみました。

