From 54ec1c4fe81672ca66f327ef6ae170f458cd79e5 Mon Sep 17 00:00:00 2001 From: shyouhei Date: Wed, 15 Aug 2007 20:57:30 +0000 Subject: sorry. I made wrong tags. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/tags/v1_8_5_54@13009 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ruby_1_8_5/ext/bigdecimal/bigdecimal_ja.html | 798 --------------------------- 1 file changed, 798 deletions(-) delete mode 100644 ruby_1_8_5/ext/bigdecimal/bigdecimal_ja.html (limited to 'ruby_1_8_5/ext/bigdecimal/bigdecimal_ja.html') diff --git a/ruby_1_8_5/ext/bigdecimal/bigdecimal_ja.html b/ruby_1_8_5/ext/bigdecimal/bigdecimal_ja.html deleted file mode 100644 index 8fd95a6fe3..0000000000 --- a/ruby_1_8_5/ext/bigdecimal/bigdecimal_ja.html +++ /dev/null @@ -1,798 +0,0 @@ - - - - - - -BigDecimal:An extension library for Ruby - - -

BigDecimal(可変長浮動少数点演算用拡張ライブラリ)

-
English

-BigDecimal はオブジェクト指向の強力なスクリプト言語である Ruby に可変長浮動小数点 -計算機能を追加するための拡張ライブラリです。 -Ruby についての詳しい内容は以下のURLを参照してください。 - -
-

目次

- - -
- -

はじめに

-Ruby には Bignum というクラスがあり、数百桁の整数でも計算することができます。 -ただ、任意桁の浮動少数点演算用クラスが無いようです。そこで、 -任意桁の浮動少数点演算用拡張ライブラリ BigDecimal を作成しました。 -不具合や助言・提案がある場合どしどし、 -
shigeo@tinyforest.gr.jp -までお知らせください。不具合を直す気は大いにあります。ただ、時間などの関係で約束 -はできません。また、結果についても保証できるものではありません。 -予め、ご了承ください。 -

-このプログラムは、自由に配布・改変して構いません。ただし、著作権は放棄していません。 -配布・改変等の権利は Ruby のそれに準じます。詳しくは README を読んでください。 - -
-

インストールについて

-BigDecimal を含む Ruby の最新版はRuby公式ページからダウンロードできます。 -ダウンロードした最新版を解凍したら、通常のインストール手順を実行して下さい。 -Ruby が正しくインストールされれば、同時に BigDecimal も利用できるようになるはずです。 -ソースファイルは -bigdecimal.c,bigdecimal.h -の2個のみです。
- -
- -

使用方法とメソッドの一覧

-「Rubyは既に書ける」という前提で、 -
-require 'bigdecimal'
-a=BigDecimal::new("0.123456789123456789")
-b=BigDecimal("123456.78912345678",40)
-c=a+b
-
-
-というような感じで使用します。 - -

メソッド一覧

-以下のメソッドが利用可能です。 -「有効桁数」とは BigDecimal が精度を保証する桁数です。 -ぴったりではありません、若干の余裕を持って計算されます。 -また、例えば32ビットのシステムでは10進で4桁毎に計算します。従って、現状では、 -内部の「有効桁数」は4の倍数となっています。 -

-以下のメソッド以外にも、(C ではない) Ruby ソースの形で -提供されているものもあります。例えば、 -

-require "bigdecimal/math.rb"
-
-とすることで、sin や cos といった関数が使用できるようになります。 -使用方法など、詳細は math.rb の内容を参照して下さい。 - -その他、Float との相互変換などのメソッドが util.rb でサポートされています。 -利用するには -
-require "bigdecimal/util.rb"
-
-のようにします。詳細は util.rb の内容を参照して下さい。 - -

クラスメソッド

- - -

インスタンスメソッド

-
-後は、読んで字の如くです。
- - -

coerceについて

-BigDecimal オブジェクトが算術演算子の左にあるときは、BigDecimal オブジェクトが -右にあるオブジェクトを(必要なら) BigDecimal に変換してから計算します。 -従って、BigDecimal オブジェクト以外でも数値を意味するものなら右に置けば -演算は可能です。
-ただし、文字列は(通常)数値に自動変換することはできません。 -文字列を数値に自動変換したい場合は bigfloat.c の -「/* #define ENABLE_NUMERIC_STRING */」のコメントを外してから、 -再コンパイル、再インストールする必要があります。 -文字列で数値を与える場合は注意が必要です。数値に変換できない文字があると、 -単に変換を止めるだけでエラーにはなりません。"10XX"なら10、"XXXX"は0 -と扱われます。
-
-   a = BigDecimal.E(20)
-   c = a * "0.123456789123456789123456789" # 文字を BigDecimal に変換してから計算
-
-無限大や非数を表す文字として、"Infinity"、"+Infinity"、"-Infinity"、"NaN" -も使用できます(大文字・小文字を区別します)。ただし、mode メソッドで false を -指定した場合は例外が発生します。 -
-また、BigDecimalクラスは coerce(Ruby本参照)をサポートしています。 -従って、BigDecimal オブジェクトが右にある場合も大抵は大丈夫です。 -ただ、現在の Ruby インタプリタの仕様上、文字列が左にあると計算できません。
-
-  a = BigDecimal.E(20)
-  c = "0.123456789123456789123456789" * a # エラー
-
-必要性があるとは思いませんが、どうしてもと言う人は - String オブジェクトを継承した新たなクラスを作成してから、 -そのクラスで coerce をサポートしてください。 - -
- -

無限、非数、ゼロの扱い

-「無限」とは表現できないくらい大きな数です。特別に扱うために - +Infinity(正の無限大)や -Infinity(負の無限大)という -ように表記されます。 -無限は 1.0/0.0 のようにゼロで割るような計算をしたときに生成されます。 -

-「非数」は 0.0/0.0 や Infinity-Infinity 等の結果が定義できない -計算をしたときに生成されます。非数は NaN(Not a Number)と表記されます。 -NaN を含む計算は全て NaN になります。また NaN は自分も含めて、どんな数 -とも一致しません。 -

-ゼロは +0.0 と -0.0 が存在します。ただし、+0.0==-0.0 は true です。 -

-Infinity、NaN、 +0.0 と -0.0 等を含んだ計算結果は組み合わせに -より複雑です。興味のある人は、以下のプログラムを実行して結果を -確認してください(結果について、疑問や間違いを発見された方は -お知らせ願います)。 - -
-
-require "bigdecimal"
-
-aa  = %w(1 -1 +0.0 -0.0 +Infinity -Infinity NaN)
-ba  = %w(1 -1 +0.0 -0.0 +Infinity -Infinity NaN)
-opa = %w(+ - * / <=> > >=  < == != <=)
-
-for a in aa
-  for b in ba
-    for op in opa
-      x = BigDecimal::new(a)
-      y = BigDecimal::new(b)
-      eval("ans= x #{op} y;print a,' ',op,' ',b,' ==> ',ans.to_s,\"\n\"")
-    end
-  end
-end
-
-
- -
-
-

内部構造

-BigDecimal内部で浮動小数点は構造体(Real)で表現されます。 -そのうち仮数部は unsigned long の配列(以下の構造体要素frac)で管理されます。 -概念的には、以下のようになります。

- <浮動小数点数> = 0.xxxxxxxxx*BASE**n

-ここで、xは仮数部を表す数字、BASEは基数(10進なら10)、nは指数部を表す -整数値です。BASEが大きいほど、大きな数値が表現できます。つまり、配列のサイズを -少なくできます。BASEは大きいほど都合がよいわけですが、デバッグのやりやすさなどを -考慮して、10000になっています(BASEはVpInit()関数で自動的に計算します)。 -これは、32ビット整数の場合です。64ビット整数の場合はもっと大きな値になります。 -残念ながら、64ビット整数でのテストはまだやっていません(もし、やられた方がいれば -結果を教えていただければありがたいです)。 -BASEが10000のときは、以下の仮数部の配列(frac)の各要素には最大で4桁の -数字が格納されます。

-浮動小数点構造体(Real)は以下のようになっています。 -
-
-  typedef struct {
-     unsigned long MaxPrec; // 最大精度(frac[]の配列サイズ)
-     unsigned long Prec;    // 精度(frac[]の使用サイズ)
-     short    sign;         // 以下のように符号等の状態を定義します。
-                            //  ==0 : NaN
-                            //    1 : +0
-                            //   -1 : -0
-                            //    2 : 正の値
-                            //   -2 : 負の値
-                            //    3 : +Infinity
-                            //   -3 : -Infinity
-     unsigned short flag;   // 各種の制御フラッグ
-     int      exponent;     // 指数部の値(仮数部*BASE**exponent)
-     unsigned long frac[1]; // 仮数部の配列(可変)
-  } Real;
-
-例えば 1234.56784321 という数字は(BASE=10000なら)
-
-    0.1234 5678 4321*(10000)**1
-
-ですから frac[0]=1234、frac[1]=5678、frac[2]=4321、 -Prec=3、sign=2、exponent=1 となります。MaxPrecは -Prec より大きければいくつでもかまいません。flag の -使用方法は実装に依存して内部で使用されます。 - -
-
-

2進と10進

-BigDecimal は <浮動小数点数> = 0.xxxxxxxxx*10**n という10進形式で数値を保持します。 -しかし、計算機の浮動小数点数の内部表現は、言うまでもなく <浮動小数点数> = 0.bbbbbbbb*2**n という -2進形式が普通です(x は 0 から 9 まで、b は 0 か 1 の数字)。 -BigDecimal がなぜ10進の内部表現形式を採用したのかを以下に説明します。 -

10進のメリット

-
-
デバッグのしやすさ -
まず、プログラム作成が楽です。frac[0]=1234、frac[1]=5678、frac[2]=4321、 -exponent=1、sign=2 なら数値が 1234.56784321 であるのは見れば直ぐに分かります。 - -
10進表記された数値なら確実に内部表現に変換できる -
例えば、以下のようなプログラムは全く誤差無しで -計算することができます。以下の例は、一行に一つの数値 -が書いてあるファイル file の合計数値を求めるものです。 -
-   file = File::open(....,"r")
-   s = BigDecimal::new("0")
-   while line = file.gets
-      s = s + line
-   end
-
-この例を2進数でやると誤差が入り込む可能性があります。 -例えば 0.1 を2進で表現すると 0.1 = b1*2**(-1)+b1*2**(-2)+b3*2**(-3)+b4*2**(-4).... -と無限に続いてしまいます(b1=0,b2=0,b3=0,b4=1...)。ここで bn(n=1,2,3,...) は -2進を表現する 0 か 1 の数字列です。従って、どこかで打ち切る必要があります。 -ここで変換誤差が入ります。もちろん、これを再度10進表記にして印刷するような -場合は適切な丸め操作(四捨五入)によって再び "0.1" と表示されます。しかし、 -内部では正確な 0.1 ではありません。 - -
有効桁数は有限である(つまり自動決定できる) -
0.1 を表現するための領域はたった一つの配列要素( frac[0]=1 )で済みます。 -配列要素の数は10進数値から自動的に決定できます。これは、可変長浮動小数点演算では -大事なことです。逆に 0.1 を2進表現したときには2進の有効桁をいくつにするのか 0.1 を -見ただけでは決定できません。 -
- -

10進のデメリット

-実は今までのメリットは、そのままデメリットにもなります。 -そもそも、10進を2進、2進を10進に変換するような操作は変換誤差 -を伴う場合を回避することはできません。 -既に計算機内部に取り込まれた2進数値を BigDecimal の内部表現に -変換するときには誤差が避けられない場合があります。 - -

最初は何か?

-自分で計算するときにわざわざ2進数を使う人は極めてまれです。 -計算機にデータを入力するときもほとんどの場合、 -10進数で入力します。その結果、double 等の計算機内部 -表現は最初から誤差が入っている場合があります。 -BigDecimal はユーザ入力を誤差無しで取り込むことができます。 -デバッグがしやすいのと、データ読みこみ時に誤差が入らない -というのが実際のメリットです。 - -
-
-

計算精度について

-c = a op b という計算(op は + - * /)をしたときの動作は -以下のようになります。

-1.乗算は(a の有効桁数)+(b の有効桁数)、 -除算は(a の最大有効桁数)+(b の最大有効桁数)分の最大桁数(実際は、余裕を持って、 -もう少し大きくなります)を持つ変数 c を新たに生成します。 -加減算の場合は、誤差が出ないだけの精度を持つ c を生成します。例えば - c = 0.1+0.1*10**(-100) のような場合、c の精度は100桁以上の精度を -持つようになります。 -

-2.次に c = a op b の計算を実行します。

-このように、加減算と乗算での c は必ず「誤差が出ない」だけの精度を -持って生成されます(BigDecimal.limit を指定しない場合)。 -除算は(a の最大有効桁数)+(b の最大有効桁数)分の最大桁数 -を持つ c が生成されますが、c = 1.0/3.0 のような計算で明らかなように、 - c の最大精度を超えるところで計算が打ち切られる場合があります。

-いずれにせよ、c の最大精度は a や b より大きくなりますので c が必要とする -メモリー領域は大きくなることに注意して下さい。 -

-注意:「+,-,*,/」では結果の精度(有効桁数)を自分で指定できません。 -精度をコントロールしたい場合は、以下のインスタンスメソッドを使用します。
- -

自分で精度をコントロールしたい場合

-自分で精度(有効桁数)をコントロールしたい場合は add、sub、mult、div 等のメソッド -が使用できます。 -以下の円周率を計算するプログラム例のように、 -求める桁数は自分で指定することができます。 -

-
-#!/usr/local/bin/ruby
-
-require "bigdecimal"
-#
-# Calculates 3.1415.... (the number of times that a circle's diameter
-# will fit around the circle) using J. Machin's formula.
-#
-def big_pi(sig) # sig: Number of significant figures
-  exp    = -sig
-  pi     = BigDecimal::new("0")
-  two    = BigDecimal::new("2")
-  m25    = BigDecimal::new("-0.04")
-  m57121 = BigDecimal::new("-57121")
-
-  u = BigDecimal::new("1")
-  k = BigDecimal::new("1")
-  w = BigDecimal::new("1")
-  t = BigDecimal::new("-80")
-  while (u.nonzero? && u.exponent >= exp) 
-    t   = t*m25
-    u   = t.div(k,sig)
-    pi  = pi + u
-    k   = k+two
-  end
-
-  u = BigDecimal::new("1")
-  k = BigDecimal::new("1")
-  w = BigDecimal::new("1")
-  t = BigDecimal::new("956")
-  while (u.nonzero? && u.exponent >= exp )
-    t   = t.div(m57121,sig)
-    u   = t.div(k,sig)
-    pi  = pi + u
-    k   = k+two
-  end
-  pi
-end
-
-if $0 == __FILE__
-  if ARGV.size == 1
-    print "PI("+ARGV[0]+"):\n"
-    p big_pi(ARGV[0].to_i)
-  else
-    print "TRY: ruby pi.rb 1000 \n"
-  end
-end
-
-
-
- - -
-小林 茂雄 - -(E-Mail:<shigeo@tinyforest.gr.jp>) - - - - - - - -- cgit v1.2.3