$0
小数がA個与えられたら、それらがどんな共通する分母の、分数であったかの推定を
するための数値計算プログラム。切り捨てと切り上げも仮定できるが、未指定なら四捨五入を仮定。
出力の読み方:
1列目: N Nは共通する分母を表す。(見つかった分子候補全てとNの全てに対して、1以外の約数かあれば、ピリオドを付加。)
2列目: B Nが分母と仮定した場合の、分子が整数になり得る場合の個数を数える。4通りの色で着色(最大,最大-1,最大-2,それ以外)。
3列目以降:
-D の指定で、各列は与えられた数値を近似する割り算の式を表示。候補が複数ある場合は分子が最小と最大の場合を;で区切て出力。
-I の指定で、分子になり得る数値の範囲を半区間表記で示す。整数を含む区間の場合は、緑色に着色する。
-Q の指定で、分子となる値を列挙する。-Dや-Iよりも簡便な表示となるが、情報が落ちる場合がある。
使用例:
$0 -g 50 0.25 0.33
# 四捨五入して、0.25 と 0.33 になるような分数で同じ分母を持つものを見つける。
# 出力される各行の最終行が 2 となるものを探せば良い。
オプション:
-c : 入力された数は、切り上げられた数であると見なす。(ceil)
-f : 入力された数は、切り捨てられた数であると見なす。(floor)
-g num : 何個の出力を得るかの指定。未指定なら12。"Inf" も指定可能。(get, greatest)
-g start,num : コロンを使うと、分母をどの数から始めるかを指定が可能。(startからnum個)
-g start,-num : numにマイナスの符号を付加すると、start から 1ずつ減少させながら 最大 num個探索する。
-y numranges : fit値(整数を区間内に持つ対応する分子の個数)がどの値の場合に、その分母の行を出力するかを指定する。,や..を使って指定。
-y , : fit値が最大の場合(引数として与えた割合の近似値の個数)のみ出力。( -y のパラメタは書式はやや複雑。)
-a num : 与えられた数値との差の絶対値が num 以下である 分数表示を見つける。(実験的実装。)
-5 2 : 既に四捨五入された値の最下位1桁をさらに四捨五入していたことを仮定する。(例. 0.45 → 0.5 → 1)
-5 num : 既に四捨五入された値のさらに何度も最下位1桁を四捨五入したことを仮定。計num回四捨五入をしたと仮定する。
-5 e : 偶数丸めをしたと見なす。(規格の ISO 31-0とJIS Z8401 を参照。) -5 e でなくて -5 E でも良い。
-5 o : 奇数丸めと見なす。-5 oも可。近似したい数の最下位が5の場合に、それを落としたい場合、最下位が奇数になるようにする。
-% : 入力された数はパーセンテージ表記(百分率)であると見なし、内部的には100分の1倍される。
-D は下記約7行で説明するように、主に除算の式を出力。除算の式が作れない場合は、分子のあり得る実数範囲を暗く表示(-Iと同様)。
-D num : 除算の式を出力。numは小数点以下の桁数。四捨五入で除算結果を出力。num=0の場合は、除算結果は見せず式のみ。
-D num% : 除算の式を出力。%表示。numは%表示で小数点以下の桁数。四捨五入で除算結果を出力。
-D -num : 除算の式と共に、ずれが分かるように、小数点以下num桁の誤差と共に示す。
-D -num% : 除算の式と共に、ずれが分かるように、小数点以下num桁のパーセントと共に示す。
-D -num%% : 除算の式と共に、ずれが分かるように、小数点以下num桁のパーミリアド(1万分の1)と共に示す。
-D -{N}ppm : 除算の式と共に、ずれが分かるように、小数点以下num桁のppm(100万分の1)と共に示す。
-D str1,str2 : -D でコンマがある場合は、前半は上記の説明の通りの指定に使われて、後半は該当する分子が存在しない場合のセルを埋めるのに使う。
-I : 分子の数値を知るべくその半区間を表示す。(Interval)
-Q : 分子の候補値全て表示。2q+1とか5q+3 など表示(qは何かの整数を意味する)。Math::Prime::Utilが導入済みなら素因数分解もする(割合の数が1個の場合)。
-2 0 : 二次情報の出力を抑制する。
-M 0 : ある分母に対して、全ての候補の分子が分母と同じ整数で割れる場合(≒約分可能)は、出力を抑制。
-L 0 : 尤度比を表示しない
-L N : 制約(合計が100%など)の個数がN個と仮定して、尤度比を算出する。
-T testname : このプログラムのテスト。testname は1,2,3, v1,v2,v3, o1,o2,o3,o4, m1 がある。
--help : このヘルプを表示する。(ただしPod::PerldocJp を一度インストールすると perldoc $0 でも可能。)
補足 :
* 半区間とは、数学的な区間[x,y)または(x,y]のような、それぞれ、x以上y未満、x超y以下のような数全体を表す。
* 負の数を入力に与えた場合は、その動作によく注意せよ。また 0 や 0.0 を与えた場合も動作に注意。要試行。
開発メモ:
* ただ1個だけの小数点以下8桁の数が渡された場合の良いアルゴリズムを考えたい。
* -Qの指定による出力については、さらに洗練の余地がある。
* 最大公約数を計算するために、普段使わない Math::BigInt を用いている。
* 入力の0に対して、-0.000が発生する謎
* 同じ数値が与えられたときに different piece で fit も反映させたい。 -s 0 でそれを解除したい。
* 偶数丸め ( JIS Z 8401 と ISO 31-0 ) に対応したい。-50を割り当てたい。しかし、大幅な改装が必要。
* 各分母に対して、対数尤度を表示する -Lのオプションを作りたい。
* "denomfind 90.5%" が意図したとおりにどうさせず。0.905と認識されなかった。90.5と認識された結果が出現し、235,236行目で数値でないという警告が出た。
* "denomfind -% 90.5%" の動作もおかしい。0.9050 と認識された。