Location : Home > Languages > Perl > Package
Title : Math::Fraction
Toolbox Logo

名称

 Math::Fraction - 分数の計算


概要

use Math::Fraction;

$a = frac(1,2); $b = frac(6,7);

print "$a + $b = ", $a + $b, "$a * $b = ", $a * $b;
print $a->num;

説明

 本プログラムは古い bigrat Perl ライブラリを置き換えることを意図している。様々なことができるが、その一端は以下の通り。

使用方法

frac(FRACTION, TAGS) || Math::Fraction->new(FRACTION, TAGS)

 ex $f1=frac(2,3); $f2=frac(7,3,MIXED); $f3=frac("-10 3/4");

 分数(FRACTION)とは以下のいずれでも表現可能)

 これらの数値は実数であるとする。負の値を指定してもよいが、Mixed (3つの値を与えるもの)の場合に最初の値が負であっても符号を無視する。
 TAGS は以下のようなものが可能である。

NORMAL | MIXED | MIXED_RAW | RAW | DEF_MIXED

 分数をどのように表示するかを指定する。

NORMAL

 #/# という形式で表示。

MIXED_RAW

 # #/# という形式で表示。

MIXED

 MIXED_RAW と同じであるが、0となる部分があればそれは表示しない。

RAW

 NORAML と同じであるが常に符号を含む。

DEF_MIXED

 実行時でのデフォルト値のままとする。

REDUCE | NO_REDUCE | DEF_REDUCE

 計算後に自動的に約分を行なうか否かを指定。

AUTO | NO_AUTO | DEF_AUTO

 BIG と SMALL との間の変換を自動的に行なうか否かを指定。AUTO タグに関する注釈を見よ。

SMALL | BIG | DEF_BIG

 AUTO タグが設定されていないときは Math::BigInt 及び Math::BigFloat パッケージを利用して任意長の数値を扱えるように変換される。(演算子はパッケージの制限のため動作しない。)
 AUTO タグが指定されているときはこれらのタグは効果がない。(デフォルトのタグは NORMAL REDUCE AUTO と SMALL であることに注意しよう。)

メソッド

reduce

 約分された分数を返す。オブジェクトは元のままである。

string(NORMAL|MIXED|MIXED_RAW|RAW)

 分数を文字列として返す。パラメータが指定されなければ用いられた書式で返す。

decimal|num

 分数を10進数に変換した値を返す。

list|list(MIXED)

 分数を含むリストを返す。MIXED が指定されていれば 3 項目を返す。

is_tag

 分数にタグがあれば 1 を返し、デフォルトに設定されていれば undef を返し、それ以外なら -1 を返す。

is_tag(INC_DEF)

 分数にタグがあれば 1 を返し、タグが存在していないがデフォルトに設定されていれば 0 を返し、それ以外なら -1 を返す。

tags

 オブジェクトタグのリストを返す。

tags(INC_DEF)

 指定したタグが読み取りようにデフォルト指定されていれば、デフォルトタグを返す代わりにオブジェクトタグのリストを返す。

 上記の全てのメソッドは最初のパラメータとして分数を用いることができるようにエクスポートできる。文字列・10進数・数値の関数はリストする代わりに STR_NUM タグでインポートできる。

modify

 オブジェクトを修正する。新規メソッドとして同じように作動するが、新規エントリによって上書きされない限り元のオブジェクトタグを保持し、何も返さない。

modify_reduce

 reduce と同じであるが、分数を返す代わりにオブジェクトを修正する。

modify_num(Numerator)

 分数の分子(numerator)を変更する。

modify_den(Denominator)

 分数の分母(denominator)を変更する。

modify_tag(TAGS)

 分数タグを変更する。

 is_tag, tags, modify_tags メソッドはデフォルトタグを取得または変更するために用いられる。以下のメソッドはクラスデフォルトを変更するために用いられる。

digits

 BIG における数値での浮動小数点演算を行なう際の、桁のデフォルト値を返す。

modify_digits(NUM)

デフォルト値集合

 デフォルト値集合(Default sets)は他の関数に影響を与えずにデフォルト値を変更する方法である。デフォルト値に依存または変更する関数は $set_id = temp_set で始まり temp_set($set_id) で終わらなければならない。どのように動作しているかを見るには使用例を参照せよ。
 以下のメソッドはクラスデフォルトで動作するようデフォルト値を管理する。

sets

 全集合のリストを返す。

name_set

 現在の集合の名称を返す。

name_set(NAME)

 現在の集合の名称を設定する。

save_set

 上記で指定された名称に基づき現在の集合を保存する。

save_set(NAME)

 現在の集合を NAME として保存する。

save_set(RAND)

 現在の集合をユニークな名称で保存する。

load_set(NAME)

 集合を呼び出す。

copy_set(NAME_ORG, NAME_NEW)

 集合を複製する。成功すれば true を返す。

del_set(NAME)

 集合を削除する。

exists_set(NAME)

 集合が存在すれば true を返す。

use_set(NAME)

 集合を設定する。ただし元の集合も変更される。

temp_set

 デフォルトの値を用いて暫定的な集合を呼び出し、保持すべきユニークなIDを返す。

temp_set(ID)

 保持しているIDに基づく元の集合を復元する。

 あらゆる指定された集合は、成功すれば集合の名称を返し、そうでなければ false を返す。

tags(SET)

 集合 SET 内のあらゆるタグのリストを返す。

is_tag(TAG, SET)

 集合 SET 内に指定したタグ TAG があれば true を返す。

digits(SET)

 集合 SET 内に設定されている文字を返す。

オーバーロードされた演算子

 以下の演算子はオーバーロードされ、分数を返す。

+  -  /  *  +  +=  -=  *=  /=  ++  -- abs

 以下の演算子もオーバーロードされている。

>=< == != > >= < <=

 以下の演算子もオーバーロードされているが醜い分数を返すかも知れない。

** sqrt

 文字列として分数にアクセスした場合には string メソッドが呼び出され、数としてアクセスした場合には decimal メソッドが呼び出される。
 これは他の他の演算子は sin や cos のような10進数を返すことを意味する。

AUTO タグに関する注釈

 AUTO タグとともに分数を用いると必要に応じて SMALL または BIG に変換される。NO_AUTO タグが明示的に指定された場合には BIG 及び SMALL タグは無視される。
 SMALL として格納するのに十分な数値であれば SMALL で格納され、必要であれば BIG に変換される。しかしながら frac(7823495784957895478,781344567825678454) のような分数は桁落ちして SMALL で格納されることになる。
 結果として BIG になる数値の計算は、まず SMALL で計算した後、BIG に変換される。
 結果として SMALL になる数値の計算は、まず BIG で計算した後、SMALL に変換される。
 通常は AUTO タグは BIG として計算することで時間を消費する。


使用例

 以下はこのモジュールがどのように動作するかを示す例である。多くの例は2つの分数で実行される。

sub pevel {print ">$_[0]\n"; $ans = eval $_[0]; print " $ans\n"; }
sub evelp {print ">$_[0]\n"; eval $_[0]; } 

 perl -e "use Math::FractionDemo; frac_calc;" と打った後に frac_demo と入力する。

>frac(1, 3)
 1/3
>frac(4, 3, MIXED)
 1 1/3
>frac(1, 1, 3)
 4/3
>frac(1, 1, 3, MIXED)
 1 1/3
>frac(10)
 10/1
>frac(10, MIXED)
 10
>frac(.66667)
 2/3
>frac(1.33333, MIXED)
 1 1/3
>frac("5/6")
 5/6
>frac("1 2/3")
 5/3
>frac(10, 20, NO_REDUCE)
 10/20

>$f1=frac(2,3); $f2=frac(4,5);
>$f1 + $f2
 22/15
>$f1 * $f2
 8/15
>$f1 + 1.6667
 7/3
>$f2->modify_tag(MIXED)
>$f2 + 10
 10 4/5
>frac($ans, NORMAL) # 異なるタグで新しい分数を生成
 54/5
>$f1 + $f2          # デフォルトモードで異なる分数を加算
 22/15
>$f1**1.2
 229739670999407/373719281884655
>$f1->num**1.2
 0.614738607654485
>frac(1,2)+frac(2,5)
 9/10

>$f1=frac(5,3,NORMAL); $f2=frac(7,5);
>"$f1  $f2"
 5/3  7/5
>Math::Fraction->modify_tag(MIXED)
>"$f1  $f2"
 5/3  1 2/5
>$f1 = frac("3267893629762/32678632179820")
 3267893629762/32678632179820
>$f2 = frac("5326875886785/76893467996910")
 5326875886785/76893467996910
>$f1->is_tag(BIG).",".$f2->is_tag(BIG) # 一方はBIGではない
 0,0
>$f1+$f2
 21267734600460495169085706/125638667885089122116217810
>$ans->is_tag(BIG)                     # 答えはBIGで
1
>$f1*$f2
 1740766377695750621849517/251277335770178244232435620
>$ans->is_tag(BIG)                     # これも同様
 1

>$f1 = frac("3267893629762/32678632179820", BIG)
 3267893629762/32678632179820
>$f1->is_tag(BIG)   # big タグは有効でない
 0
>$f1->modify_tag(NO_AUTO, BIG)
>$f1->is_tag(BIG)   # こちらでは有効。
 1
>$f1->num
 .10000093063197482237806917498797382196606
>Math::Fraction->modify_digits(15)
>$f1->num
 .1000009306319748
>$f1 = frac("0.1231231234564564564564564564561234567891234567891234")
 13680347037037036999999999999963000037/111111111000000000000000000000000000000
>Math::Fraction->modify_digits(65)
>$f1->num
 .123123123456456456456456456456123456789123456789123456789123456789

>$f1 = frac(7,5);
>$f2 = frac("3267893629762/32678632179820", NO_AUTO, BIG)
>Math::Fraction->modify_tag(MIXED); Math::Fraction->modify_digits(60)
>"$f1 ".$f2->num
 1 2/5 .1000009306319748223780691749879738219660647769485035912494771
>Math::Fraction->load_set(DEFAULT)
>"$f1 ".$f2->num
 7/5 .10000093063197482237806917498797382196606
>Math::Fraction->modify_digits(25)
>"$f1 ".$f2->num
 7/5 .10000093063197482237806917
>$s = Math::Fraction->temp_set
>Math::Fraction->modify_tag(MIXED); Math::Fraction->modify_digits(15)
>"$f1 ".$f2->num
 1 2/5 .1000009306319748
>Math::Fraction->temp_set($s)
>Math::Fraction->exists_set($s)

>"$f1 ".$f2->num  # 以前の設定に戻っている
 7/5 .10000093063197482237806917

>Math::Fraction->name_set('temp1')
>Math::Fraction->modify_tag(MIXED, NO_AUTO)
>Math::Fraction->modify_digits(60)
>&s(Math::Fraction->tags, Math::Fraction->digits)
 MIXED REDUCE SMALL NO_AUTO 60
>Math::Fraction->save_set  # 名称が何も指定されていない
>Math::Fraction->load_set(DEFAULT)
>&s(Math::Fraction->tags, Math::Fraction->digits)
  NORMAL REDUCE SMALL AUTO undef
>&s(Math::Fraction->tags('temp1'), Math::Fraction->digits('temp1'))
 MIXED REDUCE SMALL NO_AUTO 60
>  # ^^ 過去の他の集合に呼び込みなしで設定
>Math::Fraction->load_set(DEFAULT)
>Math::Fraction->use_set('temp1')
>Math::Fraction->modify_tag(NO_REDUCE)
>&s(Math::Fraction->tags, Math::Fraction->digits)
 MIXED NO_REDUCE SMALL NO_AUTO 60
>&s(Math::Fraction->tags('temp1'), Math::Fraction->digits('temp1'))
 MIXED NO_REDUCE SMALL NO_AUTO 60
>  # ^^ temp1 タグをロードしたばかりでリンクがないなら変更

注釈

 これはベータリリースである。
 オリジナルは Perl v 5.003_37 for Win32 で開発された。
 Solaris 上の Perl Ver 5.003 及び Windows95 上の perl 5.004 でテストされた。
 Linux 2 マシン上の perl v5.003 でビルドされた。
 フィードバックは kevina@clark.net に送って欲しい。
 これは私にとって最初のオブジェクト指向の Perl モジュール開発である。(ただしこれが正式なオブジェクト指向モジュールでないことは承知の上である。) Perl でのオブジェクト指向開発の勉強のためにこれを開発したようなものである。
 もっと速く、簡単な方法があれば教えて欲しい。


参考資料

 Math::FractionDemo, perl(1b)


著者と著作権

 Kevin Atkinson, kevina@clark.net

 Copyright (c) 1997 Kevin Atkinson. All rights reserved.

 本プログラムはフリーソフトウェアであり、Perl 本体と同等の条件で修正/再配布してもよい。

Toolbox Logo
Updated : 2008/04/15