Hello, Rust world!
Rustを使ってみました
今回の目標はHello, Rust world!
という出力を得ることです
まず、Rustの環境構築を行います OSはWindows10 1809です
このサイトよりRustツールチェインのインストーラをダウンロードしインストールします(リンクのためにVisual Studio等をインストールする必要があるかも)
インストールが完了したら、rustup
、rustup
、cargo
コマンドが使えるようになります
ここで、適当なディレクトリに行き、
cargo new helloworld
とコマンドを打ちます すると、helloworldディレクトリが自動で生成されます
中身はこんな感じです
. └── helloworld ├── Cargo.toml ├── .git │ ├── config │ ├── description │ ├── HEAD │ ├── hooks │ │ └── README.sample │ ├── info │ │ └── exclude │ ├── objects │ │ ├── info │ │ └── pack │ └── refs │ ├── heads │ └── tags ├── .gitignore └── src └── main.rs
main.rs
がRustのソースファイルです
一緒にgitのイニシャライズもされてますね
.gitignore
も自動で生成されていますが、出力結果のディレクトリが書いてあったりして便利です
main.rs
の中身はこうなっています
fn main() { println!("Hello, world!"); }
Hello,Worldのコードは自動で生成されているので、カレントディレクトリをhelloworldディレクトリにして
cargo run
というコマンドでコンパイル、リンク、実行がされます
Compiling helloworld v0.1.0 (適当なディレクトリ\helloworld) Finished dev [unoptimized + debuginfo] target(s) in 2.30s Running `target\debug\helloworld.exe` Hello, world!
ちゃんとHello,world!
と出力されていますね
RustでのHello,Worldは以上になります。
fn main() { println!("Hello, Rust world!"); }
内容を書き換えて
Compiling helloworld v0.1.0 (適当なディレクトリ\helloworld) Finished dev [unoptimized + debuginfo] target(s) in 1.88s Running `target\debug\helloworld.exe` Hello, Rust world!
これにて目標達成です。
今回のソースをGitHubにあげました(この程度だと必要なさそう)
高速フーリエ変換の計算量解析
高速フーリエ変換とは、離散フーリエ変換を高速に行うアルゴリズムです。 具体的にどのくらい高速なのか気になったので解析してみます。
まず、離散フーリエ変換について
要素数の入力ベクトルを、同じく出力の周波数ベクトルをとすると、離散フーリエ変換は次のような行列積で表されます。
とし、
$$
\begin{pmatrix}
f_0 \\
f_1 \\
f_2 \\
\vdots \\
f_{n-1}
\end{pmatrix}
= \begin{pmatrix}
w_n^0 & w_n^0 & w_n^0 & \cdots & w_n^0 \\
w_n^0 & w_n^1 & w_n^2 & \cdots & w_n^{n-1} \\
w_n^0 & w_n^2 & w_n^4 & \cdots & w_n^{2(n-1)} \\
\vdots & \vdots & \vdots & \ddots & \vdots \\
w_n^0 & w_n^{n-1} & w_n^{2(n-1)} & \cdots & w_n^{(n-1)^2}
\end{pmatrix}
\begin{pmatrix}
x_0 \\
x_1 \\
x_2 \\
\vdots \\
x_{n-1}
\end{pmatrix}
$$
この行列式は、回の掛け算と回の足し算を必要とするため、計算量は明らかにです。
後々のことを考えて、この真ん中の正方行列に名前をつけておきます
$$
M_n= \begin{pmatrix}
w_n^0 & w_n^0 & w_n^0 & \cdots & w_n^0 \\
w_n^0 & w_n^1 & w_n^2 & \cdots & w_n^{n-1} \\
w_n^0 & w_n^2 & w_n^4 & \cdots & w_n^{2(n-1)} \\
\vdots & \vdots & \vdots & \ddots & \vdots \\
w_n^0 & w_n^{n-1} & w_n^{2(n-1)} & \cdots & w_n^{(n-1)^2}
\end{pmatrix}
$$
そして、が2の倍数のとき(仮にの場合)、離散フーリエ変換の式はこのようになります。
$$
\begin{pmatrix}
f_0 \\
f_1 \\
f_2 \\
f_3 \\
f_4 \\
f_5 \\
f_6 \\
f_7
\end{pmatrix} =
\begin{pmatrix}
w_8^0 & w_8^0 & w_8^0 & w_8^0 & w_8^0 & w_8^0 & w_8^0 & w_8^0 \\
w_8^0 & w_8^1 & w_8^2 & w_8^3 & w_8^4 & w_8^5 & w_8^6 & w_8^7 \\
w_8^0 & w_8^2 & w_8^4 & w_8^6 & w_8^8 & w_8^{10} & w_8^{12} & w_8^{14} \\
w_8^0 & w_8^3 & w_8^6 & w_8^9 & w_8^{12} & w_8^{15} & w_8^{18} & w_8^{21} \\
w_8^0 & w_8^4 & w_8^8 & w_8^{12} & w_8^{16} & w_8^{20} & w_8^{24} & w_8^{28} \\
w_8^0 & w_8^5 & w_8^{10} & w_8^{15} & w_8^{20} & w_8^{25} & w_8^{30} & w_8^{35} \\
w_8^0 & w_8^6 & w_8^{12} & w_8^{18} & w_8^{24} & w_8^{30} & w_8^{36} & w_8^{42} \\
w_8^0 & w_8^7 & w_8^{14} & w_8^{21} & w_8^{28} & w_8^{35} & w_8^{42} & w_8^{49} \\
\end{pmatrix}
\begin{pmatrix}
x_0 \\
x_1 \\
x_2 \\
x_3 \\
x_4 \\
x_5 \\
x_6 \\
x_7
\end{pmatrix}
$$
よりこの式は次の式と等価です。
$$
\begin{pmatrix}
f_0 \\
f_1 \\
f_2 \\
f_3 \\
f_4 \\
f_5 \\
f_6 \\
f_7
\end{pmatrix} =
\begin{pmatrix}
w_8^0 & w_8^0 & w_8^0 & w_8^0 & w_8^0 & w_8^0 & w_8^0 & w_8^0 \\
w_8^0 & w_8^1 & w_8^2 & w_8^3 & w_8^4 & w_8^5 & w_8^6 & w_8^7 \\
w_8^0 & w_8^2 & w_8^4 & w_8^6 & w_8^0 & w_8^2 & w_8^4 & w_8^6 \\
w_8^0 & w_8^3 & w_8^6 & w_8^1 & w_8^4 & w_8^7 & w_8^2 & w_8^5 \\
w_8^0 & w_8^4 & w_8^0 & w_8^4 & w_8^0 & w_8^4 & w_8^0 & w_8^4 \\
w_8^0 & w_8^5 & w_8^2 & w_8^7 & w_8^4 & w_8^1 & w_8^6 & w_8^3 \\
w_8^0 & w_8^6 & w_8^4 & w_8^2 & w_8^0 & w_8^6 & w_8^4 & w_8^2 \\
w_8^0 & w_8^7 & w_8^6 & w_8^5 & w_8^4 & w_8^3 & w_8^2 & w_8^1 \\
\end{pmatrix}
\begin{pmatrix}
x_0 \\
x_1 \\
x_2 \\
x_3 \\
x_4 \\
x_5 \\
x_6 \\
x_7
\end{pmatrix}
$$
そしてこれをこのように変形します(添え字の順番が入れ替わってることに注意)
$$
\begin{pmatrix}
f_0 \\
f_2 \\
f_4 \\
f_6 \\
f_1 \\
f_3 \\
f_5 \\
f_7
\end{pmatrix} =
\begin{pmatrix}
w_8^0 & w_8^0 & w_8^0 & w_8^0 & w_8^0 & w_8^0 & w_8^0 & w_8^0 \\
w_8^0 & w_8^2 & w_8^4 & w_8^6 & w_8^1 & w_8^3 & w_8^5 & w_8^7 \\
w_8^0 & w_8^4 & w_8^0 & w_8^4 & w_8^2 & w_8^6 & w_8^2 & w_8^6 \\
w_8^0 & w_8^6 & w_8^4 & w_8^2 & w_8^3 & w_8^1 & w_8^7 & w_8^5 \\
w_8^0 & w_8^0 & w_8^0 & w_8^0 & w_8^4 & w_8^4 & w_8^4 & w_8^4 \\
w_8^0 & w_8^2 & w_8^4 & w_8^6 & w_8^5 & w_8^7 & w_8^1 & w_8^3 \\
w_8^0 & w_8^4 & w_8^0 & w_8^4 & w_8^6 & w_8^2 & w_8^6 & w_8^2 \\
w_8^0 & w_8^6 & w_8^4 & w_8^2 & w_8^7 & w_8^5 & w_8^3 & w_8^1 \\
\end{pmatrix}
\begin{pmatrix}
x_0 \\
x_2 \\
x_4 \\
x_6 \\
x_1 \\
x_3 \\
x_5 \\
x_7
\end{pmatrix}
$$
ここで、
$$
A=
\begin{pmatrix}
x_0 \\
x_2 \\
x_4 \\
x_6
\end{pmatrix}
, B=
\begin{pmatrix}
x_1 \\
x_3 \\
x_5 \\
x_7
\end{pmatrix}
, D_n =
\begin{pmatrix}
w_{2n}^0 & 0 & 0 & \cdots & 0 \\
0 & w_{2n}^1 & 0 & \cdots & 0 \\
0 & 0 & w_{2n}^2 & \cdots & 0 \\
\vdots & \vdots & \vdots & \ddots & \vdots \\
0 & 0 & 0 & \cdots & w_{2n}^{n-1}
\end{pmatrix}
$$
とおくと、なので
$$
\begin{pmatrix}
f_0 \\
f_2 \\
f_4 \\
f_6 \\
f_1 \\
f_3 \\
f_5 \\
f_7
\end{pmatrix} =
\begin{pmatrix}
M_4 A + D_4 M_4 B \\
M_4 A - D_4 M_4 B
\end{pmatrix}
$$
これを一般に拡張すると、入力ベクトルを、その半分のベクトルを (次元のベクトル)、出力ベクトルをとして
$$
F_n=M_n X_n =
\begin{pmatrix}
M_{\frac{n}{2}} A_n + D_{\frac{n}{2}} M_{\frac{n}{2}} B_n \\
M_{\frac{n}{2}} A_n - D_{\frac{n}{2}} M_{\frac{n}{2}} B_n
\end{pmatrix}
$$
ここで、とはそれぞれ要素数の離散フーリエ変換であり、1度計算すれば2度使いまわすことができます。
よって、要素数のフーリエ変換の計算量をで表すとき、
$$
f(n)=f(\frac{n}{2})+f(\frac{n}{2})+\frac{n}{2}+n
$$
回の計算が必要なので、
$$
f(n)=2 f(\frac{n}{2})+\frac{3}{2}n
$$
初期値 (掛け算1回で変換終わり)を考えると
$$
f(n)=\frac{3}{2}n \log_2 n+n
$$
となります。
よって、高速フーリエ変換の計算量はです。
【C#】Input string was not in a correct format. (TimeSpan)
TimeSpan::ToString(string)メソッドに文字列"hh:mm"を渡したらエラーが出ました
System.FormatException: Input string was not in a correct format.
解決法
':'をエスケープします
"hh:mm"=>"hh\\:mm"
【Xamarin.Forms】10分でVisual Studio App Centerを使い始める
1.Visual Studio App Center | iOS, Android, Xamarin & React NativeにアクセスしてSIGN INする
2.Add new appする
赤枠の部分は設定が必要です
ほかの部分はよしなに...
3.アプリにSDKを追加する
Microsoft.AppCenter.*なNuGetパッケージから必要なものをインストールします
4.OnCreate()内にAppCenter.Start()を追加する
それぞれのプラットフォームごとのトークン(的なの)を設定します
トークンは2.で作ったアプリ管理画面にあります
----------ここまで10分----------
【C#】Dictionary内で最小(最大)のValueをもつアイテムのKeyが知りたい
まとめ
ソートして、最初のやつ
よりも
最大値求めて、foreach
のほうが早そう
コード
最小のValueをもつアイテムのKeyを取得するサンプル
Dictionary<int,int> dict=new Dictionary<int,int>(); //ここでいろいろアイテムを追加する int maxKey=dict.OrderBy(val=>val.Value).First().Key;
最大のValueのものが欲しい場合は適当に.OrderBy()
を.OrderByDescending()
にするなどしてください
書いてて思ったんですけど.Max()
で求めた最大値を.Where()
かforeach
かでその値を持つインデックス探すほうが早い気がする
実装にもよるけど
.Max()
のオーダーは多分なので
.OrderBy()
のオーダーがだとしても.Max()
のほうが早いかと
ただまあ.OrderBy()
のほうは1行で簡単に書けるという利点(?)があるので要素数が少なくて速度を気にしなくていい場合などは使い道があるかも
【C#】nullableの挙動を確認する
int? nullable; int nonNullable;
とりあえずこんな感じの変数を使います
代入
nonNullable = 10; nullable = nonNullable; nullable = 20; nonNullable = nullable; //←コンパイルエラー nonNullable = (int)nullable; nullable = null; nonNullable = (int) nullable; //←System.InvalidOperationException
null非許容型からnull許容型への代入:問題なし
null許容型からnull非許容型への代入:キャストが必要
みたいですね
ちなみにnull許容型からnull非許容型へのキャスト時にはちゃんと値が入ってないとExceptionでるのでちゃんとnullチェックするとか??演算子使うとかしましょう
関数
オーバロード
static void Func(int? arg) { Console.WriteLine("Func-nullable"); } static void Func(int arg) { Console.WriteLine("Func-nonNullable"); }
こんな感じの関数の定義は問題なくできました
実際にこの関数を呼んだ時の動作ですが
nullable = nonNullable = 10; Func(nullable); //Func-nullable Func(nonNullable); //Func-nonNullable Func((int?)nonNullable); //Func-nullable Func((int)nullable); //Func-nonNullable
コメントで記述しているように、int?型とint型は別の型と認識されて関数が呼ばれています
キャストすれば型が変わったものと認識されるようです(当たり前か)
別の関数は呼べるのか
関数定義を変更しました
static void Func_Nullable(int? arg) { Console.WriteLine("Func_Nullable"); } static void Func_NonNullable(int arg) { Console.WriteLine("Func_NonNullable"); }
そして呼び出し側ですが
nullable = nonNullable = 10; Func_Nullable(nonNullable); Func_NonNullable(nullable); //←コンパイルエラー
nullable型の関数にnonNullableを渡すのは問題ないようです
ただ逆はエラーですね キャストしましょう
拡張関数
オーバロード
static class Extensions { public static void ExFunc(this int? arg) { Console.WriteLine("ExFunc-nullable"); } public static void ExFunc(this int arg) { Console.WriteLine("ExFunc-nonNullable"); } }
定義は問題なくできました
そしてこれを呼び出します
nullable = nonNullable = 10; nullable.ExFunc(); //ExFunc-nullable nonNullable.ExFunc(); //ExFunc-nonNullable ((int?)nonNullable).ExFunc(); //ExFunc-nullable ((int)nullable).ExFunc(); //ExFunc-nonNullable nullable?.ExFunc(); //ExFunc-nonNullable ☆ nullable = null; nullable.ExFunc(); //ExFunc-nullable nullable?.ExFunc(); //←関数が呼ばれない ☆
注目すべきは☆マークのある2つですね
nullable
がnull
でないときはint型の関数が呼ばれ、null
のときは関数が呼び出されません
この動作は拡張関数でも使えるようです
まとめ
- キャストすればなんとかなる
null許容型変数?.関数名()
の構文は拡張関数でも使える
(実は確認したかったのは拡張関数の挙動だけだったりする)
以上
【C#】stringをBASE64エンコードする(ためにstringをbyte[]に変換する)
BASE64にエンコード
バイナリをBASE64エンコードするにはSystem.Security.Cryptography.ToBase64Transform
クラス内のTransformBlock
かTransformFinalBlock
メソッドを使います
それぞれ定義はこうです
public int TransformBlock( //―Blockメソッド byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset ); public byte[] TransformFinalBlock( //―FinalBlockメソッド byte[] inputBuffer, int inputOffset, int inputCount );
引数の上3つは両方同じですね
順に入力データとオフセット(配列のどこから入力を始めるか)と入力のサイズ
―Block
メソッドの引数下二つはエンコード結果の受け取り用配列とその サイズ オフセット
―FinalBlock
メソッドのほうは結果の受け取りを戻り値でやる感じでしょうか
さてここで気づくことが一つ
「これ入力も出力もstring
じゃなくてbyte[]
だ」ですね
ということでstring
とbyte[]
の相互変換です
string⇔byte[]
string
とbyte[]
間の変換をするにはSystem.Text.Encoding
クラス内のGetBytes
とGetString
メソッドを使います
それぞれ定義は
public virtual byte[] GetBytes(string s); public virtual string GetString(byte[] bytes);
見ればわかる簡単なやつです
入れれば、変換されて、帰ってくる
わかりずらいのがEncoding
クラスのインスタンスの取得ですね
Encoding
クラス内にstatic
なインスタンスがあるのでそれを適当に使うか、同じくstatic
なGetEncoding
メソッドを使います
public static Encoding UTF8 { get; } public static Encoding UTF7 { get; } public static Encoding UTF32 { get; } public static Encoding Unicode { get; } public static Encoding BigEndianUnicode { get; } public static Encoding ASCII { get; } public static Encoding Default { get; } public static Encoding GetEncoding(string name);
ちなみにBASE64からのデコードはSystem.Security.Cryptography.FromBase64Transform
内の同名メソッドが同じ方法で使えるので説明は省略します