<link rel="self" href="https://bugs.ruby-lang.org/issues/2121.atom"/>
<link rel="alternate" href="https://bugs.ruby-lang.org/"/>
<id>https://bugs.ruby-lang.org/</id>
<icon>https://bugs.ruby-lang.org/favicon.ico</icon>
<updated>2009-09-19T14:08:34Z</updated>
<author>
<name>Ruby Issue Tracking System</name>
</author>
<entry>
<title>Ruby trunk - Bug #2121: mathn/rational destroys Fixnum#/, Fixnum#quo and Bignum#/, Bignum#quohttps://bugs.ruby-lang.org/issues/2121?journal_id=58942009-09-19T14:08:34Zheadius (Charles Nutter)headius@headius.com
<ul></ul><p>=begin<br>
One correction; 'quo' is broken in that it returns 0.333333333... in the default case and "1/3" in the mathn/rational case. These values are also of different magnitude, since 1/3 cannot be represented exactly in a floating point number.<br>
=end</p>
Ruby trunk - Bug #2121: mathn/rational destroys Fixnum#/, Fixnum#quo and Bignum#/, Bignum#quohttps://bugs.ruby-lang.org/issues/2121?journal_id=58952009-09-19T17:04:19Zheadius (Charles Nutter)headius@headius.com
<ul></ul><p>=begin<br>
On Sat, Sep 19, 2009 at 12:28 AM, Joel VanderWerf<br>
<a href="mailto:vjoel@path.berkeley.edu">vjoel@path.berkeley.edu</a> wrote:</p>
<blockquote>
<p>Perhaps it should be the responsibility of users of numeric operators to<br>
#floor explicitly when that is the intent, rather than rely on the (mostly<br>
standard, sometimes convenient, but questionable) 1/2==0 behavior. Doing so<br>
would make it easier to adapt the code to float, rational, or other numeric<br>
types.</p>
<p>In your proposal, would Rational(1,3) be the preferred notation, since<br>
1/3==0? Or would there be something else, 1//3 or ...?</p>
<p>I've always thought of mathn as a kind of alternate ruby, not just another<br>
core library, hence to be used with caution...</p>
</blockquote>
<p>I think Brian Ford expressed what I feel best...there should always be<br>
another method or operator. Using another operator or method is an<br>
explicit "buy-in" by the user--rather than a potential (at some<br>
undetermined time in the future) that everything you know about<br>
integral division in your program changes wildly. It should not be<br>
possible for any library to undermine the basic mathematical<br>
expectations of my program. Doing so, or expecting the user to do<br>
extra work to guarantee the <em>common case</em>, is a recipe for serious<br>
failure.</p>
<ul>
<li>Charlie</li>
</ul>
<p>=end</p>
Ruby trunk - Bug #2121: mathn/rational destroys Fixnum#/, Fixnum#quo and Bignum#/, Bignum#quohttps://bugs.ruby-lang.org/issues/2121?journal_id=58962009-09-19T17:07:22Zheadius (Charles Nutter)headius@headius.com
<ul></ul><p>=begin<br>
On Sat, Sep 19, 2009 at 1:01 AM, Charles Oliver Nutter<br>
<a href="mailto:headius@headius.com">headius@headius.com</a> wrote:</p>
<blockquote>
<p>integral division in your program changes wildly. It should not be<br>
possible for any library to undermine the basic mathematical<br>
expectations of my program. Doing so, or expecting the user to do<br>
extra work to guarantee the <em>common case</em>, is a recipe for serious<br>
failure.</p>
</blockquote>
<p>I will revise this slightly; it should not be possible for any <em>core<br>
library</em> to undermine the basic mathematical expectations of my<br>
program. There's a well-accepted assumption that third-party libraries<br>
are not subject to the stricter requirements of a core set, and I<br>
don't mean to say that it should not be possible to make these sorts<br>
of intriguing changes. But it should not be standard practice for any<br>
language runtime to violate key, core expectations of a programming<br>
language like the results of integral division. So I understand the<br>
utility and the intrigue, but I don't think it should be allowed in<br>
the core libraries to go that far.</p>
<ul>
<li>Charlie</li>
</ul>
<p>=end</p>
Ruby trunk - Bug #2121: mathn/rational destroys Fixnum#/, Fixnum#quo and Bignum#/, Bignum#quohttps://bugs.ruby-lang.org/issues/2121?journal_id=59122009-09-20T16:29:15Zbrixen (Brian Shirai)brixen@gmail.com
<ul></ul><p>=begin<br>
Hi,</p>
<p>On Sat, Sep 19, 2009 at 1:04 AM, Charles Oliver Nutter<br>
<a href="mailto:headius@headius.com">headius@headius.com</a> wrote:</p>
<blockquote>
<p>On Sat, Sep 19, 2009 at 12:28 AM, Joel VanderWerf<br>
<a href="mailto:vjoel@path.berkeley.edu">vjoel@path.berkeley.edu</a> wrote:</p>
<blockquote>
<p>Perhaps it should be the responsibility of users of numeric operators to<br>
#floor explicitly when that is the intent, rather than rely on the (mostly<br>
standard, sometimes convenient, but questionable) 1/2==0 behavior. Doing so<br>
would make it easier to adapt the code to float, rational, or other numeric<br>
types.</p>
<p>In your proposal, would Rational(1,3) be the preferred notation, since<br>
1/3==0? Or would there be something else, 1//3 or ...?</p>
<p>I've always thought of mathn as a kind of alternate ruby, not just another<br>
core library, hence to be used with caution...</p>
</blockquote>
<p>I think Brian Ford expressed what I feel best...there should always be<br>
another method or operator. Using another operator or method is an<br>
explicit "buy-in" by the user--rather than a potential (at some<br>
undetermined time in the future) that everything you know about<br>
integral division in your program changes wildly. It should not be<br>
possible for any library to undermine the basic mathematical<br>
expectations of my program. Doing so, or expecting the user to do<br>
extra work to guarantee the <em>common case</em>, is a recipe for serious<br>
failure.</p>
</blockquote>
<p>There are a number of issues combined here, but I think they generally<br>
reduce to these:</p>
<ol>
<li>How do you model the abstractions that are number systems in the
abstractions that are classes and methods.</li>
<li>Should the behavior of mathn be acceptable in the core language.</li>
</ol>
<p>We seem to think of the basic mathematical operations +, -, *, / as<br>
being roughly equal. But of these four, division on the integers is<br>
distinct. The set of integers is closed under addition, subtraction,<br>
and multiplication. Given any two integers, you can add, subtract, or<br>
multiply them and get an integer. But the result of dividing one<br>
integer by another is not always an integer. The integers are not<br>
closed under division. In mathematics, whether a set is closed under<br>
an operation is a significant property.</p>
<p>As such, there is nothing at all questionable about defining division<br>
on the integers to be essentially floor(real(a)/real(b)) (where<br>
real(x) returns the (mathematical) real number corresponding to the<br>
value x, because the integers are embedded in the reals and the reals<br>
are closed under division). You basically have five choices:</p>
<ol>
<li>floor(real(a)/real(b))</li>
<li>ceil(real(a)/real(b))</li>
<li>round(real(a)/real(b)) where round may use floor or ceil</li>
<li>real(a)/real(b)</li>
<li>raise an exception</li>
</ol>
<p>In computer programming, there are a number of reasons for choosing 1,<br>
2 or 3 but basically it is because that's the only way to get the<br>
"closest" integer (i.e. define division in a way that the integers are<br>
closed under the operation) . Convention has selected option 1.<br>
Numerous algorithms are implemented with the assumption that integral<br>
division is implement as option 1. It's not right or wrong, but the<br>
convention has certain advantages. In programming, we are typically<br>
implementing algorithms, not just "doing math" in some approximations<br>
of these abstractions called number systems. Any system for doing math<br>
takes serious steps to implement the real number system in as<br>
mathematically correct form as possible.</p>
<p>My contention that we should always have two operators for integral<br>
division is a compromise between the need to implement algorithms and<br>
the desire to have concise "operator" notation for doing more<br>
math-oriented computation. Given that programming in Ruby is more<br>
about algorithms than it is about doing math, it's unreasonable to<br>
expect (a/b).floor instead of a / b. At the same time, math-oriented<br>
programs are not going to be happy with a.quo b. The reasons for<br>
options 1 and 4 above are not mutually exclusive nor can one override<br>
the other.</p>
<p>The mathn library is clearly exploiting an implementation detail. Were<br>
Ruby implemented like Smalltalk (or Rubinius), mathn would have never<br>
been written as it is. The fact that it is even possible to load mathn<br>
results from the fact that countless critical algorithms in MRI are in<br>
the walled garden of C code. That's not true for your Ruby programs.<br>
Any algorithm you implement that relies on the very reasonable<br>
assumption of integral division will be broken by mathn.</p>
<p>You can say, "but mathn is in the standard library, you have to<br>
require it to use it". But that ignores the fact that requiring the<br>
library fundamentally changes assumptions that are at the very core of<br>
writing algorithms. Essential computer programming and mathn can never<br>
coexist without jumping through hoops.</p>
<p>This is the point were some grandiose scheme like selector namespaces<br>
are suggested. But I think the simple solution of two distinct<br>
operators handily solves the problem of the messy facts of<br>
mathematical number systems implemented in very untheoretic (i.e.<br>
really real) silicon.</p>
<p>As for which symbol to select, what about '/.' for real(a)/real(b).</p>
<p>Cheers,<br>
Brian</p>
<p>=end</p>
Ruby trunk - Bug #2121: mathn/rational destroys Fixnum#/, Fixnum#quo and Bignum#/, Bignum#quohttps://bugs.ruby-lang.org/issues/2121?journal_id=59342009-09-21T04:22:34Zrunpaint (Run Paint Run Run)runrun@runpaint.org
<ul></ul><p>=begin<br>
I agree that <em>mathn</em> constitutes a problem, but due to the means it employs rather than the end it achieves. In Ruby 1.8 the expectation is that '/' performs integer division, and having such a fundamental be subverted is untenable. </p>
<p>However, under Ruby 1.9, where Rational is a native class, it is altogether more reasonable that, by default, the '/' method coerce to Rational (as Lisp), preferably, or Float (as Perl and Python 3) when necessary.</p>
<p>GvR rationalizes (pun unintentional) his decision to have Python 3 perform mathematical division by default, in contrast to Python 2.0 which behaves as Ruby sans <em>mathn</em>, as follows:</p>
<p>"When you write a function implementing a numeric algorithm (for example, calculating the phase of the moon) you typically expect the arguments to be specified as floating point numbers. However, since Python doesn’t have type declarations, nothing is there to stop a caller from providing you with integer arguments. In a statically typed language, like C, the compiler will coerce the arguments to floats, but Python does no such thing – the algorithm is run with integer values until the wonders of mixed-mode arithmetic produce intermediate results that are floats."</p>
<p>"For everything except division, integers behave the same as the corresponding floating point numbers. For example, 1+1 equals 2 just as 1.0+1.0 equals 2.0, and so on. Therefore one can easily be misled to expect that numeric algorithms will behave regardless of whether they execute with integer or floating point arguments. However, when division is involved, and the possibility exists that both operands are integers, the numeric result is silently truncated, essentially inserting a potentially large error into the computation. Although one can write defensive code that coerces all arguments to floats upon entry, this is tedious, and it doesn’t enhance the readability or maintainability of the code. Plus, it prevents the same algorithm from being used with complex arguments (although that may be highly special cases)."</p>
<p><a href="http://python-history.blogspot.com/2009/03/problem-with-integer-division.html">http://python-history.blogspot.com/2009/03/problem-with-integer-division.html</a></p>
<p><a href="http://research.microsoft.com/en-us/um/people/daan/download/papers/divmodnote.pdf">http://research.microsoft.com/en-us/um/people/daan/download/papers/divmodnote.pdf</a> and <a href="http://python.org/dev/peps/pep-0238/">http://python.org/dev/peps/pep-0238/</a> are also relevant.<br>
=end</p>
Ruby trunk - Bug #2121: mathn/rational destroys Fixnum#/, Fixnum#quo and Bignum#/, Bignum#quohttps://bugs.ruby-lang.org/issues/2121?journal_id=59362009-09-21T04:52:02Zbrixen (Brian Shirai)brixen@gmail.com
<ul></ul><p>=begin<br>
Hi,</p>
<p>On Sun, Sep 20, 2009 at 9:19 AM, Rick DeNatale <a href="mailto:rick.denatale@gmail.com">rick.denatale@gmail.com</a> wrote:</p>
<blockquote>
<p>Actually in most languages which I've encountered, and that's quite a<br>
few. Mixed mode arithmetic has been implemented by having some kind of<br>
rules on how to 'overload' arithmetic operators based on the<br>
arguments, not by having different operator syntax.</p>
<p>And those rules are usually based on doing conversions only when<br>
necessary so as to preserve what information can be preserved given<br>
the arguments,</p>
<p>So, for example</p>
<p> integer op integer - normally produces an integer for all of the<br>
'big four' + - * /<br>
integer op float - normally produces a float, as does float op integer</p>
<p>As new numeric types are added, in languages which either include them<br>
inherently or allow them to be added, this pattern is usually<br>
followed.</p>
</blockquote>
<p>This is a distinctly different issue. Mixed-type arithmetic in Ruby is<br>
handled by the #coerce protocol.</p>
<blockquote>
<blockquote>
<p>As for which symbol to select, what about '/.' for real(a)/real(b).</p>
</blockquote>
<p>Well, first the problem we are talking about is Rationals, not Floats,<br>
and second, what happens as more numeric classes are introduced.</p>
</blockquote>
<p>The mathn library aliases Fixnum and Bignum #quo to #/. By default<br>
#quo returns a Float. Rational redefines #quo to produce a Rational<br>
rather than a Float.</p>
<p>But what class of object is not the point. It could be Complex. The<br>
point is that integers are not closed under division so you <em>must</em><br>
choose one of the options if you expect a value when dividing any two<br>
integers.</p>
<p>The division operation is so fundamental that assumptions about it<br>
should not change under your feet. Having a separate operator that<br>
returns a different type when integral division would be undefined<br>
allows both normal algorithms and mathy stuff to coexist nicely. In my<br>
algorithms, I <em>never</em> want my integral division to suddenly return<br>
something non-integer. In my math codes, I almost never want my<br>
quotient truncated or rounded.</p>
<p>Cheers,<br>
Brian</p>
<p>=end</p>
Ruby trunk - Bug #2121: mathn/rational destroys Fixnum#/, Fixnum#quo and Bignum#/, Bignum#quohttps://bugs.ruby-lang.org/issues/2121?journal_id=59372009-09-21T05:18:15ZRickDeNatale (Rick DeNatale)rick.denatale@gmail.com
<ul></ul><p>=begin<br>
On Sun, Sep 20, 2009 at 3:51 PM, brian ford <a href="mailto:brixen@gmail.com">brixen@gmail.com</a> wrote:</p>
<blockquote>
<p>Hi,</p>
<p>On Sun, Sep 20, 2009 at 9:19 AM, Rick DeNatale <a href="mailto:rick.denatale@gmail.com">rick.denatale@gmail.com</a> wrote:</p>
<blockquote>
<p>Actually in most languages which I've encountered, and that's quite a<br>
few. Mixed mode arithmetic has been implemented by having some kind of<br>
rules on how to 'overload' arithmetic operators based on the<br>
arguments, not by having different operator syntax.</p>
<p>And those rules are usually based on doing conversions only when<br>
necessary so as to preserve what information can be preserved given<br>
the arguments,</p>
<p>So, for example</p>
<p> integer op integer - normally produces an integer for all of the<br>
'big four' + - * /<br>
integer op float - normally produces a float, as does float op integer</p>
<p>As new numeric types are added, in languages which either include them<br>
inherently or allow them to be added, this pattern is usually<br>
followed.</p>
</blockquote>
<p>This is a distinctly different issue. Mixed-type arithmetic in Ruby is<br>
handled by the #coerce protocol.</p>
</blockquote>
<p>Not sure why it's distinctly different, what happens when a new<br>
numeric class is introduced, e.g. Rational, is what we seem to be<br>
talking about.</p>
<p>And #coerce is just an implemention detail whose motivation seems to<br>
be in line with what I'm saying.</p>
<blockquote>
<blockquote>
<blockquote>
<p>As for which symbol to select, what about '/.' for real(a)/real(b).</p>
</blockquote>
<p>Well, first the problem we are talking about is Rationals, not Floats,<br>
and second, what happens as more numeric classes are introduced.</p>
</blockquote>
<p>The mathn library aliases Fixnum and Bignum #quo to #/. By default<br>
#quo returns a Float. Rational redefines #quo to produce a Rational<br>
rather than a Float.</p>
<p>But what class of object is not the point. It could be Complex. The<br>
point is that integers are not closed under division so you <em>must</em><br>
choose one of the options if you expect a value when dividing any two<br>
integers.</p>
</blockquote>
<p>Right, and Ruby like most other languages made a choice to use integer<br>
division, rather than converting.</p>
<p>Smalltalk made another choice, to return a Fraction when dividing two integers.</p>
<p>In both cases, the / operator is effectively overloaded, and can<br>
return other kinds of numbers given different pairs of arguments.</p>
<blockquote>
<p>The division operation is so fundamental that assumptions about it<br>
should not change under your feet. Having a separate operator that<br>
returns a different type when integral division would be undefined<br>
allows both normal algorithms and mathy stuff to coexist nicely. In my<br>
algorithms, I <em>never</em> want my integral division to suddenly return<br>
something non-integer. In my math codes, I almost never want my<br>
quotient truncated or rounded.</p>
</blockquote>
<p>Yes, I agree that I don't want the rules to change under my feet. I<br>
want a / b to give me the same integer as Ruby 1.8 sans mathn gives me<br>
when a and b are integers, and I expect 1 / 1.2 to give me the same<br>
float etc. I'm not sure I see the need for additional operators, but<br>
that's a side issue.</p>
<p>Run Paint Run suggested that 1.9 SHOULD produce a Rational or maybe a<br>
float as the result of dividing two integers, because "that what Guido<br>
would do."</p>
<p>The brutal facts are that there's is lots of code written in Ruby, and<br>
lots of that code uses integer divide, and would be broken if this<br>
change were made, it would be the same as silently including mathn in<br>
every existing ruby program, which seems like a bad idea.</p>
<p>Guess what! I did some experimentation with irb1.9 and was pleasantly<br>
surprised to find that 1.9 seems to be doing quite the opposite, it<br>
acts just like the "thought experiment" proposal I suggested here.</p>
<p>$ irb1.9<br>
irb(main):001:0> Rational<br>
=> Rational<br>
irb(main):002:0> 1/2<br>
=> 0<br>
irb(main):003:0> Rational(1)<br>
=> Rational(1, 1)<br>
irb(main):004:0> 1.to_r<br>
=> Rational(1, 1)</p>
<p>Which I guess indicates that "that's what Matz would do."</p>
<p>-- <br>
Rick DeNatale</p>
<p>Blog: <a href="http://talklikeaduck.denhaven2.com/">http://talklikeaduck.denhaven2.com/</a><br>
Twitter: <a href="http://twitter.com/RickDeNatale">http://twitter.com/RickDeNatale</a><br>
WWR: <a href="http://www.workingwithrails.com/person/9021-rick-denatale">http://www.workingwithrails.com/person/9021-rick-denatale</a><br>
LinkedIn: <a href="http://www.linkedin.com/in/rickdenatale">http://www.linkedin.com/in/rickdenatale</a></p>
<p>=end</p>
Ruby trunk - Bug #2121: mathn/rational destroys Fixnum#/, Fixnum#quo and Bignum#/, Bignum#quohttps://bugs.ruby-lang.org/issues/2121?journal_id=59382009-09-21T07:56:39Zrunpaint (Run Paint Run Run)runrun@runpaint.org
<ul></ul><p>=begin</p>
<blockquote>
<p>Run Paint Run suggested that 1.9 SHOULD produce a Rational or maybe a<br>
float as the result of dividing two integers, because "that what Guido<br>
would do."</p>
</blockquote>
<p>He said, of course, no such thing. I suggest that when your strawman necessitates the sensationalist mis-characterization of another's position that amateur rhetoric may not be your calling. In fact, your pastiche is not even internally consistent because GvR did not advocate rational results.</p>
<p>I was simply illustrating that other, similar languages have faced this issue, and so providing a justification for, and the results of, their decisions. </p>
<blockquote>
<p>The brutal facts are that there's is lots of code written in Ruby, and<br>
lots of that code uses integer divide, and would be broken if this<br>
change were made, it would be the same as silently including mathn in<br>
every existing ruby program, which seems like a bad idea.</p>
</blockquote>
<p>The same argument can always be rallied to support inertia. As we progress toward Ruby 2.0 it behooves us to revisit our prior decisions and consider whether they remain defensible in hindsight. Further, your analogy is flawed: it would not at all "be the same as silently including mathn in every existing ruby program", because neither would such a change in language semantics be ushered in "silently", nor does <em>mathn</em> perform only this function.</p>
<blockquote>
<p>Which I guess indicates that "that's what Matz would do."</p>
</blockquote>
<p>The existence of an "infallible designer" would obviate this very bug tracker, as every aspect of the language could be reasoned so. It indicates what the current behavior is, nothing more.</p>
<p>As to the matter at hand, Brian's solution seems eminently reasonable for 1.8 at least; the desired behavior of <em>mathn</em> and '/' under 1.9 is perhaps a separate issue.<br>
=end</p>
Ruby trunk - Bug #2121: mathn/rational destroys Fixnum#/, Fixnum#quo and Bignum#/, Bignum#quohttps://bugs.ruby-lang.org/issues/2121?journal_id=60222009-09-25T19:23:57Ztadf (tadayoshi funaba)
<ul><li><strong>Assignee</strong> set to <i>keiju (Keiju Ishitsuka)</i></li></ul><p>=begin</p>
<p>=end</p>
Ruby trunk - Bug #2121: mathn/rational destroys Fixnum#/, Fixnum#quo and Bignum#/, Bignum#quohttps://bugs.ruby-lang.org/issues/2121?journal_id=62012009-10-12T13:22:43ZRickDeNatale (Rick DeNatale)rick.denatale@gmail.com
<ul></ul><p>=begin<br>
On Sun, Sep 20, 2009 at 3:29 AM, brian ford <a href="mailto:brixen@gmail.com">brixen@gmail.com</a> wrote:</p>
<blockquote>
<p>Hi,</p>
<p>On Sat, Sep 19, 2009 at 1:04 AM, Charles Oliver Nutter<br>
<a href="mailto:headius@headius.com">headius@headius.com</a> wrote:</p>
<blockquote>
<p>On Sat, Sep 19, 2009 at 12:28 AM, Joel VanderWerf<br>
<a href="mailto:vjoel@path.berkeley.edu">vjoel@path.berkeley.edu</a> wrote:</p>
<blockquote>
<p>Perhaps it should be the responsibility of users of numeric operators to<br>
#floor explicitly when that is the intent, rather than rely on the (mostly<br>
standard, sometimes convenient, but questionable) 1/2==0 behavior. Doing so<br>
would make it easier to adapt the code to float, rational, or other numeric<br>
types.</p>
<p>In your proposal, would Rational(1,3) be the preferred notation, since<br>
1/3==0? Or would there be something else, 1//3 or ...?</p>
<p>I've always thought of mathn as a kind of alternate ruby, not just another<br>
core library, hence to be used with caution...</p>
</blockquote>
<p>I think Brian Ford expressed what I feel best...there should always be<br>
another method or operator. Using another operator or method is an<br>
explicit "buy-in" by the user--rather than a potential (at some<br>
undetermined time in the future) that everything you know about<br>
integral division in your program changes wildly. It should not be<br>
possible for any library to undermine the basic mathematical<br>
expectations of my program. Doing so, or expecting the user to do<br>
extra work to guarantee the <em>common case</em>, is a recipe for serious<br>
failure.</p>
</blockquote>
<p>There are a number of issues combined here, but I think they generally<br>
reduce to these:</p>
<ol>
<li>How do you model the abstractions that are number systems in the
abstractions that are classes and methods.</li>
<li>Should the behavior of mathn be acceptable in the core language.</li>
</ol>
<p>We seem to think of the basic mathematical operations +, -, *, / as<br>
being roughly equal. But of these four, division on the integers is<br>
distinct. The set of integers is closed under addition, subtraction,<br>
and multiplication. Given any two integers, you can add, subtract, or<br>
multiply them and get an integer. But the result of dividing one<br>
integer by another is not always an integer. The integers are not<br>
closed under division. In mathematics, whether a set is closed under<br>
an operation is a significant property.</p>
<p>As such, there is nothing at all questionable about defining division<br>
on the integers to be essentially floor(real(a)/real(b)) (where<br>
real(x) returns the (mathematical) real number corresponding to the<br>
value x, because the integers are embedded in the reals and the reals<br>
are closed under division). You basically have five choices:</p>
<ol>
<li>floor(real(a)/real(b))</li>
<li>ceil(real(a)/real(b))</li>
<li>round(real(a)/real(b)) where round may use floor or ceil</li>
<li>real(a)/real(b)</li>
<li>raise an exception</li>
</ol>
<p>In computer programming, there are a number of reasons for choosing 1,<br>
2 or 3 but basically it is because that's the only way to get the<br>
"closest" integer (i.e. define division in a way that the integers are<br>
closed under the operation) . Convention has selected option 1.<br>
Numerous algorithms are implemented with the assumption that integral<br>
division is implement as option 1. It's not right or wrong, but the<br>
convention has certain advantages. In programming, we are typically<br>
implementing algorithms, not just "doing math" in some approximations<br>
of these abstractions called number systems. Any system for doing math<br>
takes serious steps to implement the real number system in as<br>
mathematically correct form as possible.</p>
<p>My contention that we should always have two operators for integral<br>
division is a compromise between the need to implement algorithms and<br>
the desire to have concise "operator" notation for doing more<br>
math-oriented computation. Given that programming in Ruby is more<br>
about algorithms than it is about doing math, it's unreasonable to<br>
expect (a/b).floor instead of a / b. At the same time, math-oriented<br>
programs are not going to be happy with a.quo b. The reasons for<br>
options 1 and 4 above are not mutually exclusive nor can one override<br>
the other.</p>
</blockquote>
<p>Actually in most languages which I've encountered, and that's quite a<br>
few. Mixed mode arithmetic has been implemented by having some kind of<br>
rules on how to 'overload' arithmetic operators based on the<br>
arguments, not by having different operator syntax.</p>
<p>And those rules are usually based on doing conversions only when<br>
necessary so as to preserve what information can be preserved given<br>
the arguments,</p>
<p>So, for example</p>
<pre> integer op integer - normally produces an integer for all of the
</pre>
<p>'big four' + - * /<br>
integer op float - normally produces a float, as does float op integer</p>
<p>As new numeric types are added, in languages which either include them<br>
inherently or allow them to be added, this pattern is usually<br>
followed.</p>
<p>Smalltalk has the concept of generality of a number class. More<br>
general classes can represent more numbers, albeit with some potential<br>
for adding 'fuzziness' in the standard image Floats are the most<br>
general, then Fractions, then equally LargePositiveIntegers and<br>
LargeNegativeIntegers (which together serve the same role as Bignum in<br>
Ruby), then SmallInteger (Ruby's Fixnum).</p>
<blockquote>
<p>The mathn library is clearly exploiting an implementation detail. Were<br>
Ruby implemented like Smalltalk (or Rubinius), mathn would have never<br>
been written as it is. The fact that it is even possible to load mathn<br>
results from the fact that countless critical algorithms in MRI are in<br>
the walled garden of C code. That's not true for your Ruby programs.<br>
Any algorithm you implement that relies on the very reasonable<br>
assumption of integral division will be broken by mathn.</p>
</blockquote>
<p>The problem with mathn is that it introduces new numeric types, and<br>
also changes the behavior of the existing types, particularly integer,<br>
so that when mathn is included</p>
<pre>integer / integer produces a rational if the result can't be
</pre>
<p>reduced to an integer.</p>
<p>This is at odds with most languages and, as Charles points out, it<br>
effectively changes the 'rules of physics' for other code which is<br>
likely unaware that mathn has been introduced.</p>
<p>In Smalltalk, there is a standard Fraction class and integer division<br>
does in fact return a Fraction rather than an Integer. But that's<br>
known and expected by Smalltalk programmers.</p>
<blockquote>
<p>You can say, "but mathn is in the standard library, you have to<br>
require it to use it". But that ignores the fact that requiring the<br>
library fundamentally changes assumptions that are at the very core of<br>
writing algorithms. Essential computer programming and mathn can never<br>
coexist without jumping through hoops.</p>
</blockquote>
<p>Yes this is a problem IMHO. The difference between Ruby and Smalltalk<br>
here is that one language starts out including Rationals/Fractions,<br>
and the other treats them as an optional add on which, when added,<br>
changes the rules.</p>
<blockquote>
<p>This is the point were some grandiose scheme like selector namespaces<br>
are suggested. But I think the simple solution of two distinct<br>
operators handily solves the problem of the messy facts of<br>
mathematical number systems implemented in very untheoretic (i.e.<br>
really real) silicon.</p>
<p>As for which symbol to select, what about '/.' for real(a)/real(b).</p>
</blockquote>
<p>Well, first the problem we are talking about is Rationals, not Floats,<br>
and second, what happens as more numeric classes are introduced.</p>
<p>Another alternative would be to change mathn (or maybe make a new<br>
alternative mathn for compatibility for programs already using mathn)<br>
which</p>
<pre>1. Left 1 / 2 as producing the Integer 1
2. Allowed explicit instantiation of Rationals
* Rational.new(1,2) # i.e. make the new method public.
* Change Object#Rational to always return a Rational for an
</pre>
<p>integer argument, with a denominator of 1.<br>
* Integer#to_rational which could be implemented as:<br>
class Integer<br>
def to_rational<br>
Rational(self)<br>
end<br>
end</p>
<p>Then rational arithmetic could be implemented so that</p>
<pre> 5 / 3 => 1
5.to_rational / 3 => 5 / 3
5 / 3.to_rational => 5 / 3
(5.to_r / 3).to_i => 1
</pre>
<p>Which would be in-line with standard arithmetic in Ruby IMHO.</p>
<p>Note: it might be more ruby-like to name the coercion method to_r<br>
instead of to_rational, but that might be confused by some as meaning<br>
something else like to real, although I don't really thing that that<br>
would be that much of an issue.</p>
<p>-- <br>
Rick DeNatale</p>
<p>Blog: <a href="http://talklikeaduck.denhaven2.com/">http://talklikeaduck.denhaven2.com/</a><br>
Twitter: <a href="http://twitter.com/RickDeNatale">http://twitter.com/RickDeNatale</a><br>
WWR: <a href="http://www.workingwithrails.com/person/9021-rick-denatale">http://www.workingwithrails.com/person/9021-rick-denatale</a><br>
LinkedIn: <a href="http://www.linkedin.com/in/rickdenatale">http://www.linkedin.com/in/rickdenatale</a></p>
<p>=end</p>
Ruby trunk - Bug #2121: mathn/rational destroys Fixnum#/, Fixnum#quo and Bignum#/, Bignum#quohttps://bugs.ruby-lang.org/issues/2121?journal_id=133492010-09-14T16:14:09Zshyouhei (Shyouhei Urabe)shyouhei@ruby-lang.org
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Assigned</i></li></ul><p>=begin</p>
<p>=end</p>
Ruby trunk - Bug #2121: mathn/rational destroys Fixnum#/, Fixnum#quo and Bignum#/, Bignum#quohttps://bugs.ruby-lang.org/issues/2121?journal_id=182582011-06-26T13:53:07Zakr (Akira Tanaka)akr@fsij.org
<ul><li><strong>Project</strong> changed from <i>Ruby</i> to <i>Ruby trunk</i></li></ul> Ruby trunk - Bug #2121: mathn/rational destroys Fixnum#/, Fixnum#quo and Bignum#/, Bignum#quohttps://bugs.ruby-lang.org/issues/2121?journal_id=329762012-11-17T01:29:03Zheadius (Charles Nutter)headius@headius.com
<ul></ul><p>This is still an issue. Requiring a standard library should never change the result of a Fixnum operation. The current behavior is a terrible bug.</p>
Ruby trunk - Bug #2121: mathn/rational destroys Fixnum#/, Fixnum#quo and Bignum#/, Bignum#quohttps://bugs.ruby-lang.org/issues/2121?journal_id=329842012-11-17T02:39:32Zmarcandre (Marc-Andre Lafortune)ruby-core@marc-andre.ca
<ul><li><strong>Description</strong> updated (<a title="View differences" href="/journals/32984/diff?detail_id=23277">diff</a>)</li><li><strong>Category</strong> set to <i>lib</i></li></ul><p>It does create some problems in real apps (e.g. <a href="https://github.com/rails/rails/pull/8222">https://github.com/rails/rails/pull/8222</a> )</p>
<p>The problem is compatibility. I always thought that it was the intent of <code>mathn</code> to change the semantics of <code>/</code> so that the same operations would have different meanings. For example <code>Matrix[[1]] / 2</code> returns different results depending on the presence of <code>mathn</code> or not.</p>
<p>Avoiding the problem is trivial: when you mean "division with truncation to integer", use <code>Integer#div</code> instead of <code>Integer#/</code>.</p>
<p><code>div</code> has the advantage of being crystal clear, since <code>foo.div(bar)</code> always truncates down to an integer, while <code>foo / bar</code> can return any of Integer, Rational, Float, BigDecimal, Complex, Matrix, Vector, etc., depending on the classes of foo, bar (and if mathn is loaded or not)</p>
<p>What I'm trying to say is that, given the choices made in the past, using <code>/</code> instead of <code>div</code> can be seen as a user mistake, although it clearly is an easy one to make. Ideally, library/framework authors would be aware of this and reserve <code>Integer#/</code> for mathematical libraries and use <code>div</code> where appropriate.</p>
<p>I don't see how we can change the current behavior, but adding a note in the doc for <code>Integer#/</code> about this could not hurt.</p>
Ruby trunk - Bug #2121: mathn/rational destroys Fixnum#/, Fixnum#quo and Bignum#/, Bignum#quohttps://bugs.ruby-lang.org/issues/2121?journal_id=330152012-11-17T19:16:07Zheadius (Charles Nutter)headius@headius.com
<ul></ul><p>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.</p>
<p>Another example of why this sucks, from a Ruby implementer perspective...</p>
<p>In JRuby, the basic math operations are recognize and optimized for better performance...all except #/ because of the mathn problem. Silly, isn't it?</p>
Ruby trunk - Bug #2121: mathn/rational destroys Fixnum#/, Fixnum#quo and Bignum#/, Bignum#quohttps://bugs.ruby-lang.org/issues/2121?journal_id=484962014-08-27T02:44:20Zhsbt (Hiroshi SHIBATA)hsbt@ruby-lang.org
<ul><li><strong>Related to</strong> <i><a class="issue tracker-2 status-5 priority-4 priority-default closed" href="/issues/10169">Feature #10169</a>: It might be better to make Mathn class deprecated</i> added</li></ul> Ruby trunk - Bug #2121: mathn/rational destroys Fixnum#/, Fixnum#quo and Bignum#/, Bignum#quohttps://bugs.ruby-lang.org/issues/2121?journal_id=484972014-08-27T02:45:02Zhsbt (Hiroshi SHIBATA)hsbt@ruby-lang.org
<ul><li><strong>Status</strong> changed from <i>Assigned</i> to <i>Closed</i></li></ul><p>mathn library is deprecated on trunk [Feature <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: It might be better to make Mathn class deprecated (Closed)" href="https://bugs.ruby-lang.org/issues/10169">#10169</a>]</p>
Ruby trunk - Bug #2121: mathn/rational destroys Fixnum#/, Fixnum#quo and Bignum#/, Bignum#quohttps://bugs.ruby-lang.org/issues/2121?journal_id=485032014-08-27T04:25:19Zheadius (Charles Nutter)headius@headius.com
<ul></ul><p>Bravo!</p>