Project

General

Profile

Bug #11183

Cumulative error on Complex::I ** 100000000000000000000000000000000

Added by ko1 (Koichi Sasada) about 4 years ago. Updated about 4 years ago.

Status:
Open
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-dev:49002]

Description

p Complex::I ** 100000000000000000000000000000000

が、32bit 環境だと、

ruby 2.3.0dev (2015-05-21 trunk 50502) [i386-mswin32_110]
t.rb:1: warning: in a**b, b may be too big
(-0.08483712490438944+1.5651333429325577e+32i)

こんな感じで、変な値が出ます。

# ubuntu 64bit だと
(0.9943722416631883-0.10594264962575697i)

できれば、こっちも 1+0i にぴたっとしてるといいのでしょうが。

この問題に対する、うささんのコメント:

真面目にコードを読むと、Complex#** は引数(指数)がFixnumでない場合は複素数をいったん極座標形式に変換してからrとθの双方をそれぞれ計算し、最後にf_complex_polarを使ってComplexオブジェクトにしてるのですが、θはFloatなので当然に誤差が蓄積し、という感じです。まあ、誤差が蓄積しなかったとしても、f_complex_polarの中でせっかくθが0°・90°・180°・270°のケースを特別扱いしようとしてるのにdouble値を==で比較してるのでまったく救われそうにない、という感じではありますが。
θをn倍する計算に対して、nが整数である場合は360°は0°と同じという性質を利用して誤差を蓄積しない計算をすればだいぶマシになるとは思いますが、しかしめんどくさいっすね。


Files

my_complex.diff (2.09 KB) my_complex.diff usa (Usaku NAKAMURA), 05/26/2015 08:30 AM

History

Updated by usa (Usaku NAKAMURA) about 4 years ago

めんどくさいと言いつつ、手元には、添付のような「誤差を蓄積しない計算」を試してみたパッチがありますが(コンセプトを確認するためのもので実用ではない)、次は「45°とかは?」という話になることは明らかなのでびみょーです。
より賢い方法が求められていると思われます。

Also available in: Atom PDF