https://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112015-05-26T08:32:45ZRuby Issue Tracking SystemRuby master - Bug #11183: Cumulative error on Complex::I ** 100000000000000000000000000000000https://bugs.ruby-lang.org/issues/11183?journal_id=526332015-05-26T08:32:45Zusa (Usaku NAKAMURA)usa@garbagecollect.jp
<ul><li><strong>File</strong> <a href="/attachments/5249">my_complex.diff</a> <a class="icon-only icon-download" title="Download" href="/attachments/download/5249/my_complex.diff">my_complex.diff</a> added</li></ul><p>めんどくさいと言いつつ、手元には、添付のような「誤差を蓄積しない計算」を試してみたパッチがありますが(コンセプトを確認するためのもので実用ではない)、次は「45°とかは?」という話になることは明らかなのでびみょーです。<br>
より賢い方法が求められていると思われます。</p> Ruby master - Bug #11183: Cumulative error on Complex::I ** 100000000000000000000000000000000https://bugs.ruby-lang.org/issues/11183?journal_id=1053102023-11-13T20:02:58ZJesseJohnson (Jesse Johnson)
<ul></ul><p>This behavior still exists in Ruby 3.2.2.</p>
<p>In order to fix this Complex#** would need to handle the special cases of self being 0+1i and 0-1i.</p>
<p>Correct:</p>
<pre><code>irb(main):052:0> Complex(0, -1) ** 1000000000000000000
=> (1+0i)
irb(main):053:0> Complex(0, -1) ** 1000000000000000001
=> (0-1i)
irb(main):054:0> Complex(0, -1) ** 1000000000000000002
=> (-1+0i)
irb(main):055:0> Complex(0, -1) ** 1000000000000000003
=> (0+1i)
irb(main):056:0> Complex(0, -1) ** 1000000000000000004
=> (1+0i)
irb(main):057:0> Complex(0, 1) ** 1000000000000000000
=> (1+0i)
irb(main):058:0> Complex(0, 1) ** 1000000000000000001
=> (0+1i)
irb(main):059:0> Complex(0, 1) ** 1000000000000000002
=> (-1+0i)
irb(main):060:0> Complex(0, 1) ** 1000000000000000003
=> (0-1i)
irb(main):061:0> Complex(0, 1) ** 1000000000000000004
=> (1+0i)
</code></pre>
<p>Suboptimal:</p>
<pre><code>irb(main):066:0> Complex(0, -1) ** 10000000000000000000
(irb):66: warning: in a**b, b may be too big
=> (-0.9125701512929312+0.40892018655135703i)
irb(main):067:0> Complex(0, -1) ** 10000000000000000001
(irb):67: warning: in a**b, b may be too big
=> (-0.9125701512929312+0.40892018655135703i)
irb(main):068:0> Complex(0, -1) ** 10000000000000000002
(irb):68: warning: in a**b, b may be too big
=> (-0.9125701512929312+0.40892018655135703i)
irb(main):069:0> Complex(0, -1) ** 10000000000000000003
(irb):69: warning: in a**b, b may be too big
=> (-0.9125701512929312+0.40892018655135703i)
irb(main):070:0> Complex(0, -1) ** 10000000000000000004
(irb):70: warning: in a**b, b may be too big
=> (-0.9125701512929312+0.40892018655135703i)
irb(main):071:0> Complex(0, 1) ** 10000000000000000000
(irb):71: warning: in a**b, b may be too big
=> (-0.9125701512929312-0.40892018655135703i)
irb(main):072:0> Complex(0, 1) ** 10000000000000000001
(irb):72: warning: in a**b, b may be too big
=> (-0.9125701512929312-0.40892018655135703i)
irb(main):073:0> Complex(0, 1) ** 10000000000000000002
(irb):73: warning: in a**b, b may be too big
=> (-0.9125701512929312-0.40892018655135703i)
irb(main):074:0> Complex(0, 1) ** 10000000000000000003
(irb):74: warning: in a**b, b may be too big
=> (-0.9125701512929312-0.40892018655135703i)
irb(main):075:0> Complex(0, 1) ** 10000000000000000004
(irb):75: warning: in a**b, b may be too big
=> (-0.9125701512929312-0.40892018655135703i)
irb(main):076:0> in):070:0> Complex(0, -1) ** 10000000000000000004
=> (-0.9125701512929312-0.40892018655135703i)
</code></pre> Ruby master - Bug #11183: Cumulative error on Complex::I ** 100000000000000000000000000000000https://bugs.ruby-lang.org/issues/11183?journal_id=1053402023-11-16T12:20:39Zkyanagi (Kouhei Yanagita)
<ul></ul><p><a href="https://github.com/ruby/ruby/pull/8931" class="external">https://github.com/ruby/ruby/pull/8931</a></p>
<p>self の偏角が45度の整数倍であるような場合に特別扱いするようにしてみました。</p>
<pre><code>1i ** (10 ** 100) #=> 1+0i
1i ** (10 ** 100 + 1) #=> 0+1i
(1+1i) ** (10 ** 100) # warning: in a**b, b may be too big
#=> (Infinity+0.0i)
(1+1i) ** (10 ** 100 + 1) # warning: in a**b, b may be too big
#=> (Infinity+Infinity*i)
</code></pre>
<ul>
<li>self が 1, -1, 1i, -1i の場合
<ul>
<li>bignum 乗であっても正しい答えを返します。</li>
</ul>
</li>
<li>self が実数または純虚数で絶対値が1でない場合</li>
<li>偏角が 45 度の奇数倍である場合
<ul>
<li>小さい数(大きい数)が0(Infinity)となりますが、その前提のもとで正しい答えを返します。</li>
</ul>
</li>
</ul>
<p>絶対値が 1 で偏角が 45 度の奇数倍である複素数は、実部・虚部(1/\sqrt{2})をFloatで正確に表現することはできないため、<br>
偏角が45度の奇数倍である複素数オブジェクトの n 乗は、絶対値が1からずれていくことになります。</p>
<p>なお、60 度など他の角度についてですが、偏角が 45 度の整数倍を除く有理数度である複素数は、Complex では正確には表現できません。(実部または虚部のいずれかが無理数になる)<br>
従って、Complex オブジェクトの偏角は 45 度の整数倍であるか無理数であるかになるため、<br>
偏角を n 倍することで n 乗を求める計算が誤差なしでできるのは、偏角が 45 度の整数倍の場合に限られることになります。</p> Ruby master - Bug #11183: Cumulative error on Complex::I ** 100000000000000000000000000000000https://bugs.ruby-lang.org/issues/11183?journal_id=1053602023-11-21T05:06:40Zkyanagi (Kouhei Yanagita)
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Closed</i></li></ul><p>Applied in changeset <a class="changeset" title="[Bug #11183] Fix rb_complex_pow for special angles Add a special treatment for when the argument..." href="https://bugs.ruby-lang.org/projects/ruby-master/repository/git/revisions/04eb40b633397d03e4cbce41418626f4fabdcb02">git|04eb40b633397d03e4cbce41418626f4fabdcb02</a>.</p>
<hr>
<p>[Bug <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Cumulative error on Complex::I ** 100000000000000000000000000000000 (Closed)" href="https://bugs.ruby-lang.org/issues/11183">#11183</a>] Fix rb_complex_pow for special angles</p>
<p>Add a special treatment for when the argument of self is an<br>
integral multiple of 45 degrees.</p>
<p>1i ** (10 ** 100) #=> 1+0i<br>
1i ** (10 ** 100 + 1) #=> 0+1i<br>
(1+1i) ** (10 ** 100) # warning: in a<strong>b, b may be too big<br>
#=> (Infinity+0.0i)<br>
(1+1i) ** (10 ** 100 + 1) # warning: in a</strong>b, b may be too big<br>
#=> (Infinity+Infinity*i)</p>