Forum: Ruby-core mathn/rational destroys Fixnum#/, Fixnum#quo and Bignum#/, Bignum#quo

Posted by Charles Nutter (headius)
on 2012-11-17 11:16
(Received via mailing list)
Issue #2121 has been updated by headius (Charles Nutter).


I sympathize with the desire to avoid breaking backward compatibility, 
but the idea that "10 / 2" is the wrong way and you should instead use 
"10.div(2)" is pretty anti-Ruby. This is terribly surprising and 
certainly not what any user would expect. I would suggest that a new 
method be added to Integer for the variable behavior...something like 
#ratio or #fraction.

Another example of why this sucks, from a Ruby implementer 
perspective...

In JRuby, the basic math operations are recognize and optimized for 
better performance...all except #/ because of the mathn problem. Silly, 
isn't it?
----------------------------------------
Bug #2121: mathn/rational destroys Fixnum#/, Fixnum#quo and Bignum#/, 
Bignum#quo
https://bugs.ruby-lang.org/issues/2121#change-33015

Author: headius (Charles Nutter)
Status: Assigned
Priority: Normal
Assignee: keiju (Keiju Ishitsuka)
Category: lib
Target version:
ruby -v: Any 1.8.6 or higher


=begin
 I've known this for a while, but only now realized this is actually a 
terrible bug.

 The mathn library replaces Fixnum#/ and Bignum#/ causing them to return 
a different value. When the result of a division is not an integral 
value, the default versions will return 0. I can think of many 
algorithms that would use this expectation, and most other languages 
will not upconvert integral numeric types to floating-point or 
fractional types without explicit consent by the programmer.

 When requiring 'mathn', Fixnum#/ and Bignum#/ are replaced with 
versions that return a fractional value ('quo') causing a core math 
operator to return not just a different type, but *a different value*.

 No core library should be allowed to modify the return value of core 
numeric operators, or else those operators are worthless; you can't rely 
on them to return a specific value *ever* since someone else could 
require 'mathn' or 'rational'.

 Note also that 'rational' destroys Fixnum#quo and Bignum#quo. This is 
also a bug that should be fixed, though it is less dangerous because 
they're not commonly-used operators.

 The following code should not fail; Fixnum#/ should never return a 
value of a different magnitude based on which libraries are loaded:

 {{{
 require 'test/unit'

 class TestFixnumMath < Test::Unit::TestCase
   # 0 to ensure it runs first, for illustration purposes
   def test_0_without_mathn
     assert_equal 0, 1/3
   end

   def test_with_mathn
     require 'mathn'
     assert_equal 0, 1/3
   end
 end
 }}}

 But it does fail:

 {{{
 ~/projects/jruby ➔ ruby test_fixnum_math.rb
 Loaded suite test_fixnum_math
 Started
 .F
 Finished in 0.016003 seconds.

   1) Failure:
 test_with_mathn(TestFixnumMath) [test_fixnum_math.rb:11]:
 <0> expected but was
 <1/3>.

 2 tests, 2 assertions, 1 failures, 0 errors
 }}}
=end
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.