スキップしてメイン コンテンツに移動

投稿

10月, 2017の投稿を表示しています

Rustで科学計算 (2) Vec型

1. 配列とVec型 Rustの配列は, その長さが コンパイル時に 既に固定されている必要があります. 従って, 最初から長さのわかっているベクトルを扱う場合には, 例えばその長さNを const N: usize = 128; とコンパイル時定数として導入することで, 素直に配列をつくることができます. const N: usize = 128; fn main() { let x: [ f64; N ] = [ 0.; N ]; } 一方, コンパイル時には長さが決まっておらず実行時に動的に決定される場合, または実行時にコマンドライン引数として長さを与えたい場合, コンパイル時には配列の長さが決まっていない訳なので, それを配列として実現することはできません. そのような状況ではVec型 (Vectorとも) を利用しましょう. 2. Vec型の宣言と要素の追加, 参照, 削除 例えば要素が既知のi32型を要素とするVec型変数 a は let a: Vec<i32> = vec![ 0, 1, 2, 3, 4 ]; により宣言できます. あるいは, f64型を要素として持つことのできる空のVec型変数 v を宣言するには let mut v: Vec<f64> = Vec::new(); とします. いま変数 v には何も要素がないので, そこに要素を追加するには v.push(0.0) とすればよいです. 要素をpushするためには変数がmutableであることが必要です. また, Vectorの要素の型はすべて共通でなければなりません. なお, あらかじめvectorの要素数が, 例えば上限128と見当がついているのならば let mut v: Vec<f64> = Vec::with_capacity(128); とした方が高速に動作します. もちろんこの場合でも128を超えて要素を追加することは可能です. Vector v の要素の値は配列と同じく v[i] によりアクセスできます. 要素数がNのとき, 引数 i は0からN-1までの値を取り, その範囲外の要素にアクセスしようとするとpanicが引き起こされます. vector v の i 番目の要素を削除したい

matplotlib.histのnormedが変

以下の内容はPython 3.5.2 + matplotlib 1.5.1およびPython 3.6.2 + matplotlib 2.0.2で検証した. 作業日は2017年10月22日, 前者はUbuntu 16.04 on Win10 (WSL), 後者はDebian 8.9 (Anaconda). 規格化したいのにできない なにか数値の列 data があったとして, そのヒストグラムをmatplotlibでプロットしたいとする. 普通に plt.hist( data ) とすると, これは縦軸が各bin内に入るデータ点が何個あるかを表すことになる. これをデータ総数 len(data) で規格化したプロットにしようと思って plt.hist( data, normed=True ) または normed=1 とかやっちゃうと, 思った通りのアウトプットにならずに頭を傾げることになる. 例えば: import numpy as np import matplotlib.pyplot as plt data = np.random.normal(0,0.1,1000) weights = np.ones(len(data))/len(data) plt.hist( data, weights=weights ) plt.show() アウトプットは で, 縦軸が1を超えるとか, 意味がわからない. 原因 matplotlibのドキュメント を見ても何も書いてない. これは numpyのドキュメント に答えが書いてあるからで, 要するに normed オプションは事実上 density オプションと等しく, これは縦軸を確率分布関数と思って規格化するオプションである, と. 従って, normed=True オプションを指定すると, binの 面積 が1に規格化されることになる. いま欲しいものは値の 総和 が1に規格化されたアウトプットなのだから, binの幅が1でない限り, 欲しい結果は得られない. 対策 代わりに weights オプションを指定すればこの問題は解決できる. これは data の1つの値の重みを指定するパラメー

Rustで科学計算 (1) データのasciiファイル書き出し

結論 use std::io::prelude::*; use std::fs::File; fn main() { /* この辺で計算 */ let s = format!("filename_{:03}.txt", i ); let mut buffer = File::create(s).unwrap(); write!(buffer, "{:.04} {:.04} {:.04} {:.04}\n", t, x, y, z ); } ファイルの書き出し 計算結果をファイルに書き出すためには, s をファイル名として let mut buffer = File::create(s).unwrap(); により出力ファイルを用意する. 既に同名のファイルが存在する場合には上書きされる (もとのデータは消去される). あとは write!(buffer, 文字列) により用意したバッファーに任意に書き込んでいけばよい. 本当は書き出し失敗用のエラーに対処するようにコードを書く必要がある (し, 上の例だとコンパイル時に警告される) が, 個人使用する上では必要性を感じないので, とりあえず放置してある. コードの可読性の方が大事. 数値出力のフォーマット 整数型の場合, "{}", i とかしておけばよい. 桁数をそろえてゼロ埋めするには, 例えば "{:04}", i で4桁になる. 実数型の場合, "{:.04}", t で小数点以下4桁まで. 指数表記は "{:e}" とか "{:.03e}" みたいな感じ.