実数→実数
出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2018/08/02 06:48 UTC 版)
一般の正の実数に対しては、二進対数は次の2段階の手順で計算できる。 整数部分 ⌊ lb x ⌋ {\displaystyle \lfloor \operatorname {lb} \,x\rfloor } を計算する。 小数部分を計算する。 まず、整数部分の計算は簡単である。任意の正の実数 x に対して、2n ≦ x < 2n+1 となるような整数 n が唯一に定まる。この各辺を 2n で割った 1 ≦ x/2n < 2 という式を立ててもよい。これをもって、二進対数の整数部分を n と定める。そして、この n を使って、小数部分を lb (x/2n) と表記することにする。すなわち、y = x/2n と置くと、次のようになる。 lb x = n + lb y ただし、1 ≦ y < 2 小数部分 lb y は、掛け算と割り算のみを使って再帰的に計算できる。この計算手順は以下のとおりとなる。 まず、1 ≦ y < 2 から出発する。y = 1 ならば、小数部分は0となって、その時点で終了である。 y > 1 ならば、y を繰り返し2乗して、2 ≦ z < 4 なる実数 z を得る。2乗した回数を m とすると、 z = y ( 2 m ) {\displaystyle z=y^{(2^{m})}} となる。 この式の両辺の対数をとり、式変形を行うと次のようになる。 lb z = 2 m lb y lb y = lb z 2 m = 1 + lb ( z / 2 ) 2 m = 2 − m + 2 − m lb ( z / 2 ) {\displaystyle {\begin{aligned}\operatorname {lb} \,z&=2^{m}\operatorname {lb} \,y\\\operatorname {lb} \,y&={\operatorname {lb} \ z \over 2^{m}}\\&={1+\operatorname {lb} (z/2) \over 2^{m}}\\&=2^{-m}+2^{-m}\operatorname {lb} (z/2)\end{aligned}}} この m の値を記録しておく。 2乗する作業をやめる基準は 2 ≦ z < 4 であった。したがって、1 ≦ z/2 < 2 となっている。そこであらためて y := z/2 と置き、この新しい y の二進対数を同じ手法で計算する。 そして最終的に、lb x を次のように計算する。以下、m[i] は、アルゴリズムの i 回目の繰り返しにおいて2乗の操作を行った回数とする。 lb x = n + 2 − m [ 1 ] ( 1 + 2 − m [ 2 ] ( 1 + 2 − m [ 3 ] ( 1 + ⋯ ) ) ) = n + 2 − m [ 1 ] + 2 − m [ 1 ] − m [ 2 ] + 2 − m [ 1 ] − m [ 2 ] − m [ 3 ] + ⋯ {\displaystyle {\begin{aligned}\operatorname {lb} \,x&=n+2^{-m[1]}\left(1+2^{-m[2]}\left(1+2^{-m[3]}\left(1+\cdots \right)\right)\right)\\&=n+2^{-m[1]}+2^{-m[1]-m[2]}+2^{-m[1]-m[2]-m[3]}+\cdots \end{aligned}}} ある時点で y = 1 となった場合には、この計算は当然、そこまでで終了する。逆に、永久に y = 1 とならない場合には、この式は無限級数となるが、すべての i について m[i] ≧ 1 が成り立つので、どの項もその直前の項より小さくなっている。よって、比較判定法により、この級数が必ず収束するということがわかる。 実用上は、計算に無限の時間を費やすわけにはいかないので、計算を途中で打ち切った近似値を使うことになる。級数の i 番目の項より後ろを切り捨てた場合の誤差の上限は、(1/2)m[1]+m[2]+…+m[i] である。 しかし実際には幸いなことに、このような高コストな計算も、無限級数の切り捨ても必要とせずに、 値を2乗する。 結果が2以上であれば、2で割る。 という計算を繰り返すのみで簡単に対数を得ることができる。具体的なコードを Microsoft Visual Basic で記述すると、下記のとおりとなる。(なお、この実装ではわかりやすさのために、関数の戻り値を2進表現の文字列としてある。当然ながら、その後の計算のためには、何らかの方法で数値型のデータにしなければならない。) Function lb(ByVal y As Double, ByVal numDigits As Integer) as String Dim result As String result = "0." If y < 1 Or 2 <= y Then lb = "1≦y<2の値を渡してください。" Exit Function End If While numDigits > 0 y = y * y If 2 <= y Then result = result & "1": y = y / 2 Else result = result & "0" End If numDigits = numDigits - 1 Wend lb = resultEnd Function 例として、1.65の二進対数を4ビットの精度で計算する(すなわち、上記の関数を lb(1.65, 4) として呼び出す)ケースを考える。このプログラムを逐次追いかけていくと次のようになる。 まず、このプログラムでは整数位の計算が既に終わっていることを前提とする(すなわち、1 ≦ y < 2 となっていることを要求する)ので、無条件で "0." の2文字を書く。 与えられた y = 1.65 を2乗すると2.72となる。これは2以上なので、小数1桁目として1を書く。この2.72を2で割って1.36を得る。 1.36を2乗すると1.85となる。これは2より小さいので、2で割ることはせず、2桁目として0を書く。 1.85を再度2乗すると3.43となる。これは2以上なので、3桁目として1を書く。この3.43を2で割って1.72を得る。 1.72を2乗すると2.95となる。これは2以上なので、4桁目として1を書く。ほしい精度は4ビットなので、これで計算終了とする。 こうして0.1011という数字列を得たので、 lb 1.65 ≒ 0.1011(2) = 13/16 と確定させる。このとき、誤差は1/16未満となっている。さらにもう1ビット計算すれば27/32となり、誤差は1/32未満となる。一般に、m ビットの精度がほしい(すなわち、誤差を (1/2)1+m 未満としたい)ときには、2乗の計算をちょうど m 回、2で割る計算を最大 m 回行えば必要十分である。
※この「実数→実数」の解説は、「二進対数」の解説の一部です。
「実数→実数」を含む「二進対数」の記事については、「二進対数」の概要を参照ください。
- 実数→実数のページへのリンク