簡単な計算をするときに長らく重宝していたのがcalcというソフト。コマンドラインから十分な精度で計算してくれる。非常に便利で、私はここ数年というもの、毎日のように使っていた。
- calc "9**100"
265613988875874769338781322035779626829233452653394495974574961739092490901302182994384699044001 - calc 1/10
0.1 - calc "sqrt(2)"
1.4142135623730950488
別にPython起動してもいいんですけどね。シェルの入力でそのまま計算できるというのは便利なもんです。
しかしFedoraならいいけど、EPELにパッケージがないのでCentOSでは使いにくいという問題があった。しょうがないので自分でrpm作って入れてたんです。
そこに登場したのがPythonのeval()をうまく使ったclacというソフト。似たような使い勝手で、Pythonなので無限桁の整数を苦もなく使える。拡張もやりやすい。ソースはPythonのスクリプト1本なので、Cygwinのような環境にも持ち歩ける(Cygwinのパッケージには入ってませんが)。
これは良い! 非常に!!
…のだけど、
- clac "9**100"
265613988875874769338781322035779626829233452653394495974574961739092490901302182994384699044001 - clac 1/10
0.10000000000000001 - clac "sqrt(2)"
1.4142135623730951
うーむ。浮動小数点の演算で誤差が入るのはどうもアレですよねー。
しかし、拡張可能というのがこういう時に使えることを私は知っている。Pythonには分数や10進演算のモジュールがある。分数は確かPython 2.7以降だから入ってない古い環境もあるかもしれないが。なので、~/.clacrcに以下のように書いておく。
try: from fractions import Fraction frac=Fraction except ImportError,detail: #old python pass from decimal import Decimal dec=Decimal
これによって、正確に計算することができるのだ。
- clac "dec(1)/10"
0.1 - clac "frac(1)/10"
1/10
ちょっと変な計算だってできる。まああまりに凝ったものならPythonを起動したほうがゴニョゴニョ…
- clac "min(3,2,5)"
2 - clac "map(lambda f: f**2, [5,2,3])"
25,4,9
16進数や2進数での出力も。Pythonのバージョンが古いと2進数はダメですが。
- clac "bin(10**10)"
0b1001010100000010111110010000000000 - clac "hex(99979**20)"
0x12360D70241827049F39B016F8F033F71E6CA4C37A526FFE06BB97EB9CEEC0FBBAF2F203830C74DAFDF1L
例えば、N進数の表示をする関数を定義しても良いだろう。
def nary(v, n=10): import string nary_digits=string.digits+string.ascii_lowercase assert(len(nary_digits)>=n) r=[] while v!=0: r.append(nary_digits[int(v%n)]) v=long(v/n) r.reverse() return "".join(r)
- clac "hex(10**10)"
0x2540BE400L - clac "nary(10**10, 16)"
2540be400 - clac "nary(10**10, 30)" ← 30進数
dlfkb3a
でも、clacの環境だとこのnary()、可哀想にどこかで浮動小数点数に変わってしまうみたいで、桁数が多くなるとダメです。普通にPythonの関数として呼ぶと大丈夫なんですけどね…なんだかなぁ。
- Python>>> nary(99979**20, 16)
12360d70241827049f39b016f8f033f71e6ca4c37a526ffe06bb97eb9ceec0fbbaf2f203830c74dafdf1 - clac "hex(99979**20)"
0x12360D70241827049F39B016F8F033F71E6CA4C37A526FFE06BB97EB9CEEC0FBBAF2F203830C74DAFDF1L - clac "nary(99979**20, 16)"
12360d702418270000000000000000000000000000000000000000000000000000000000000000000001