要旨
プログラムを作成する中で、複数の状態量を一定のルールで1つの数字(仮に$x$とする)に落とし込むことがある。今回取り上げるのはそんな中でもよくありそうな
\begin{equation}
x = am + n
\end{equation}
\begin{eqnarray}
\verb|s.t.|
\\
m&\in&\mathbb{R}
\\
n&\in&\mathbb{R}
\end{eqnarray}
な場合を取り上げる。
このとき、$x$および$a$が与えられ$m$および$n$をプログラムで導出するならば、つぎの2つの手法が考えられる。
- $x \div a$の整数部分を求めて、次に$x - a \times \verb|(整数部分)|$を求める
- $x \div a$の剰余(
mod(x,a)
)を求めて、次に$(x - \verb|mod(x,a)|) \div a$を求める
[int] $m = 13;
[int] $n = 7;
[int] $a = 8;
[int] $x = $a * $m + $n;
$quotient = [Math]::Floor([Decimal]($x / $a));
$remainder = $x - $quotient * $a;
[int] $m = 13;
[int] $n = 7;
[int] $a = 8;
[int] $x = $a * $m + $n;
$remainder = $x % $a;
$quotient = ($x - $remainder) / $a;
1.のコードの特徴は、明示的にDecimal型へキャストを行い、さらにその小数部を切り捨てる処理を記述している点である。メモリーの使用量と内部で行われる処理の複雑さを考えると計算機に与える負荷は2.のコードよりも大きいと考える。
2.のコードの特徴は、演算結果である$x$に対して演算過程を逆にたどることで値を得ている点である。この場合は明示的なキャストや実数に対する切り落とし処理を行わなくてよい分、簡潔で計算負荷が小さいと考える。
このようなコード実装に対して、以下の3点が論点されることがある。
- 処理に必要な記憶域
- 計算量
- コードの可視性、理解容易性
筆者は次の表のように評価する。
記憶域 | 計算量 | 可視性 | |
---|---|---|---|
1.のコード | 大 | 大 | 可 |
2.のコード | 小 | 小 | 優 |
仕様に数学的処理が定義されている論理の実装の際には、「何を得たいか」だけに着目するのではなく、「その値はどのようにして生成されたのか」に着目することで、可視性と計算量の双方を考慮したコーディングを実現することが容易となる。
なんでこんな記事書いたのさ
要旨と言いながら長くなりましたなぁ(Extended Abstractに全部書いちゃう病の人)。
いえですね、こんなことがありまして。
トントン:社内のルーターがなんかおかしい。ログないかなぁ。
ルーター:30件ならあるで?ただしこけた時のログはないし、再起動したらログは全部飛ぶんや。
トントン:F〇ck'n Shit! えぇい。Syslogサーバーはないのか?
上司:よくわかんないから立ててない。Windows Serverでできたっけ?(MS信者)
トントン:もういいもん UDPで受信すればいいんでしょ?たしか。
というわけで簡易SyslogサーバーめいたものをPowerShellで動かそうと思ったんですね。
んで、Syslogのパケットの仕様見ながら参考にするコードを探していたら、出会ってしまったんです。商と余りを取得するのにDecimalにキャストしたうえでFloorで切り捨てをするコードに。
「『商と余り』だから、まず割り算して丸めよう」という考え方
悪くはないと思います。その処理が1回こっきりでめったに出てこないんだったら。
でも、このコードは500msec.ごとにこの処理呼んでる……
それはないんじゃない?
というわけで、この記事を書きました。
きっとあるであろう突込み
Cacti使いなよ