dポイントプレゼントキャンペーン実施中!

今日は!
Windowsの関数は、例えばlog(1000)の計算を比較的短時間で行います。
この計算は、テーラー級数を使用しているのでしょうか
否、他の計算方法を使用しているのでしょうか?
もしテーラー級数を使用しているのであれば、その収束はどの様に解決している
のでしょうか?
Q1)log(1000)の場合について、具体的にC++のコードでご回答頂けますと
 大変有り難いです。

以上、宜しくお願いします。

質問者からの補足コメント

  • C++(又はjava)の場合は、具体的にどのように計算しているのでしょうか?
    具体的にlog(1000)の場合に、または一般的にどのアルゴリズムで計算している
    のでしょうか?
    ここら辺に詳しい方の、ご回答をお願いします。

      補足日時:2015/09/18 12:17
  • >そういうのは実装依存で、一般的というのはありません。
    <---貴方は、上記のコメントを書かれましたが、貴方の回答の最後の部分で次のコメント
    があります。
    >あと、これは一般的だと思いますが。
    .....
    // 底の変換とか、log x^n = n log x, .....
    <---つまり私の質問は、log(1000)でも、log(1000.9)でも、その解を得る
    アルゴリズムについて質問したわけで、私はこれを一般的といいました。
    相手に疑問を持たせるコメントはとうかな?
    貴方の紹介された、http://www.netlib.org/fdlibm/e_log.c には、回答らしきものが書かれていますが、画面表示の関係でその内容を読取ることが出来ません。
    もし、上記サイトのe_log.cの内容を、通常のプログラム形式で表示(拝見)する方法はありますか?
    以上

    No.3の回答に寄せられた補足コメントです。 補足日時:2015/09/18 23:47

A 回答 (5件)

> もし、上記サイトのe_log.cの内容を、通常のプログラム形式で表示(拝見)する方法はありますか?



ダウンロードして保存して、テキストエディタで開いてください。
その e_log.c はC言語のソースコードそのものです。
実際にコンパイルするには http://www.netlib.org/fdlibm/ にある一式が必要かもしれません(試していません)

中を見ると、 メインの部分は sqrt(2)/2 < 1+f < sqrt(2) のときの log(1+f) を精度よく近似するものです。
この範囲を越えるような x については、 x = 2^k *(1 +f) となる k を探して (1+f) の対数を計算し、その後、元のlog(x)になるように計算しています。
log(1000) なら、
log(1000)
→ log(2^10 * 0.9765625)
→ 10 * log(2) + log(0.9765625)
と変形してから、 log(0.9765625) を求めます。


学校で習ったかと思いますが、logには「底の変換」等いくつかの公式があります。
log_a(x) を直接計算できなくても、 これらの公式を使って「計算できる底、真数だけの式」( t + s・log_b(y) 等)に変形すれば計算できます。



これはFdLibm というライブラリでの1例であって「一般的にこのアルゴリズムが使われている」というわけではありません。
実際に、glibcでは別のアルゴリズムが使われているようです。
底や真数によってアルゴリズムを使い分ける場合もあるでしょう。
Visual C++での実装や IntelのCPUに組み込まれた実装は、アルゴリズムが公開されているわけではないので、何が使われているかわかりません。

正解が一つではないので、回答も曖昧にせざるをえません。
    • good
    • 0
    • good
    • 0
この回答へのお礼

アイデアーとしては、面白いので、お礼としてベストアンサーを差し上げました。

お礼日時:2015/09/19 07:52

そういうのは実装依存で、一般的というのはありません。



例えば、GCCで使われているC標準ライブラリglibcは、ソースが公開されています
https://github.com/lattera/glibc
これを辿っていくと
・対数演算命令のあるFPUを搭載した環境では、その命令を使うようにアセンブリで書かれている
例) https://github.com/lattera/glibc/blob/master/sys …
・そうで無い場合は近似値を計算: ソースを見る限り、計算済みのテーブルを使って補間しているように見える。
例) https://github.com/lattera/glibc/blob/master/sys …

ということがわかります。

また、FdLibm というライブラリでは、アルゴリズムがコメントに書いてあります。
http://www.netlib.org/fdlibm/e_log.c




あと、これは一般的だと思いますが。
特定の範囲のx,yについてのlog_y(x) を求めることができれば、公式を使っていろんな値の対数を計算できます
// 底の変換とか、log x^n = n log x, log (xz) = log x + log z とか
この回答への補足あり
    • good
    • 0

今どきのPCだとCPU内蔵命令一発なので具体的な計算方法は分からないでしょうね。



何らかの事情で自前で計算するなら適当に範囲を限定して近似関数を使うのが良いでしょう。

ここで範囲の限定というのは例えば
1000=2^10*(1000/1024)なので、
log(1000)=10*log(2)+log(1000/1024)
となり、log(2)は特定の定数なのであらかじめ計算しておけばよく
log(1000/1024)は1000/1024が1に近いので、log(x)の近似計算はxが1に近いところだけできれば十分ということです。
実際には例えば3/4<=x<3/2になるように調整します。

ただし近似関数としてlogのテーラー展開は収束が遅い&収束範囲が狭いで実際の計算には使いにくいでしょう。単純なテーラー展開でなく有理関数型の展開式が有効です。
例えば下記PDFの8ページ目(文書内p.64)の(6.11)を使えば、上の範囲限定と併用して15項まで計算すれば倍精度浮動小数点の限界くらいまで計算できるでしょう。
# http://na-inet.jp/nasoft/chap06.pdf

なお単精度なら5項くらいで十分なので、どこまで計算するかは目的次第ですね。
    • good
    • 1

昔ならともかく、昨今のCPU、すくなくとも、最近のWindowsが動作しているようなCPUなら、浮動小数点演算専用の回路(FPU)が入っています。


FPUには、対数計算する命令が入っています(少なくとも、最近のWindowsが動作しているようなインテル系のFPUなら)


FPU内での具体的な計算方法までは知りません。
ですが、ハードウエアであることを活用した手法が使われており、C++のプログラムにしたらかえって効率が悪くなるようなものもあるだろう、と想像できます。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


このQ&Aを見た人がよく見るQ&A