开发者

understanding numbers in ruby rationals

开发者 https://www.devze.com 2023-03-04 04:58 出处:网络
from http://www.ruby-doc.org/core/classes/Rational.html Rational(10) / 3#=> (10/3) Rational(10) / 3.0 #=> 3.3333333333333335

from http://www.ruby-doc.org/core/classes/Rational.html

Rational(10) / 3   #=> (10/3)
Rational(10) / 3.0 #=> 3.3333333333333335

Rational(-8) ** Rational(1, 3)
                  #=> (1.0000000000000002+1.7320508075688772i)

I understand the first two, but not the last one. Note that Rational(8) ** Rational(1, 3) works just fine, and there is no floating point context to muddy the waters. Can someone explain this to me, and how to get -2 like I am supposed to get?

edit: note that I don't mean how to get -2 just in this instance, but how to in general working with rationals detect that complex number representation is necessary and switch context appropriately.

edit #2 (thanks to pst and Mat): As per pst's example:

>> (Rational(-8) ** Rational(1,3)) ** Rational(3)
=> (-8.0+3.1086244689504383e-15i)

This is a great example of why I care to return a Real answer when possible (I would be much more forgiving if this was the Complex class spitting back complex numbers, but this is the Rational class — I'm going to dare to say that it should be behaving rationally). Mat's answer illustr开发者_Python百科ates why one might want a general solution, like a monkey patch to Rationals (or complex class, etc) or a wrapper class: because otherwise I can't lazy code my way through handling basic mathematical operations with relative precision.

I think I see the roots of an answer in Mat's response, but it's not immediately clear to me how to convert this into a monkey patch or wrapper class that will behave properly in general code.


The answer is not -2: the answer is 2i. Whoops, math fail. In any case, parts of the rest are still relevant in some fashion. See Mat's comment and Sawa's answer.

This doesn't explain why there isn't just a pretty 2i (or (0+2i)) in the output, I suspect it is just due to internal rounding errors (it doesn't try to replace matlab). See Sawa's answer for how to "understand" the result of the complex number returned.

See Imaginary Numbers and Complex Numbers for the notation used in the result.

Consider:

>> (Rational(-8) ** Rational(1,3)) ** Rational(3)                       
=> (-8.0+3.1086244689504383e-15i)

That's not far off!

However,

>> (Rational(8) ** Rational(1,3)) ** Rational(3)                        
=> 8.0

Is "perfect". Hopefully someone can run with this.

Happy coding.


Edit, okay, here is what happens: The result of Rational ** Rational is not a Rational.

When the result is real Rational ** Rational -> Float, but when the result contains an imaginary component, then Rational ** Ration -> Complex.

In the "perfect" case, we just stayed within the bounds of Float accuracy (at least enough to get a "pretty result"). In the case resulting in the Complex object, because of being stored in a real + imaginary part and then math being performed upon the data later, the bounds of the relative precision Float of the combined components wasn't good enough.


The easiest way is to write your own root function to find the real root, which checks the sign if the root you want is odd, and restores it afterwards. Essentially:

(-8) ** (1/3) = -(8 ** 1/3)

I had a similar problem in another language (see here) and one of the members there gave a pretty good explanation of why that is.


(1.0000000000000002+1.7320508075688772i) is probably representing 1+\sqrt{3}i, and it is (one of) the correct answer(s):

(1+\sqrt{3}i)^3 = -8

What is wrong with it?

Probably, you forgot the fundamental theorem of algebra? The root is not unique. But since the return value in this case is to be a number, there must be some criteria (which may follow from the ruby-internal algorithm) that chose this particular one. If you want to chose a different root, then you have to explicitly code that part on your own. One way to do it is

-Rational(8) ** Rational(1, 3)
# => -2.0

But note that that still gives you a float. That's because, once you introduce a fractional power, it is not closed within rational number anymore. If you still want a rational answer 2, you would probably have to use a software that at least can solve polynomial equations.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号