[RCR] Floating point division operator /. (or fdiv method)

  • Thread starter Michael Neumann
  • Start date
B

Bret Jolly

Paul Brannan said:
I use / all the time to indicate integer division (provided I'm working
with integers). My code will not work with mathn and I have no
intention of going out of my way to uglify my code just to make it
compatible with a broken library.

Then your code is incompatible with the standard libraries and
you should not be writing anything other people will use. The
rational, complex, and matrix libraries need mathn in order
to work properly. In particular, matrix gives dramatically wrong
answers without so much as a warning if you don't include mathn.
The real problem is that mathn should be required automatically,
and it isn't, even when failure to require it gives incontrovertibly
wrong answers. See my previous posts on these issues for examples.

Regards, Bret
 
J

Jim Weirich

Paul said:
I strongly disagree. It is mathn that is broken, not the / operator.

Hi Paul! I still think / is broken, even without considering mathn.
There are two separate operations intdiv and floatdiv with different
semantics. / will do one or the other, but you don't know which one it
is unless you know the exact types of the operands. I don't know of a
single algorithm where this polymorphism is useful. And *every* use of
/ must process (check or convert) any operand that comes from outside
your local code. This is broken in my opinion.

This is one area where (IMHO) Python took the right choice. (I can't
believe I said that).

Anyways, this is obviously an area where reasonable people can have
different opinions.

Take care.

Matz: Thanks for pointing out quo. I missed that one.
 
M

Michael Neumann

Hi Paul! I still think / is broken, even without considering mathn.
There are two separate operations intdiv and floatdiv with different
semantics. / will do one or the other, but you don't know which one it
is unless you know the exact types of the operands. I don't know of a
single algorithm where this polymorphism is useful. And *every* use of
/ must process (check or convert) any operand that comes from outside
your local code. This is broken in my opinion.

That's exactly what I tried to express in this RCR... polymorphism in
this case is not that good. Thanks for your good explanation.

There wouldn't be a problem if // would be the integer division
operator, then mathn would work correctly, because it doesn't matter
whether float_div or rational_div is used for / (except for precision
and speed).
This is one area where (IMHO) Python took the right choice. (I can't
believe I said that).

Well, I believed that's how Python works as well. But in Python (2.3):
0
0
0.0
0.5
0.5

So they have the same "problem" as we in Ruby. But AFAIK, they can
better control the impacts than Ruby can (limited to module scope?).

IMO, Ruby 2.0 "should" behave this way:

1 / 2 # => 0.5 or Rational(1/2)
1 // 2 # => 0
1.0 // 2 # => 0 (any good reason to return 0.0 here?)

With selector namespaces in Ruby 2.0 (?), and the addition of the //
operator, we could go this way. Old libraries could overload / to behave
as is Ruby < 2.0, whereas new libraries could use the new behaviour.

Regards,

Michael
 
M

Mark Sparshatt

Michael said:
Well, I believed that's how Python works as well. But in Python (2.3):

0.5

So they have the same "problem" as we in Ruby. But AFAIK, they can
better control the impacts than Ruby can (limited to module scope?).
However GvR has decided to fix the problem in the way you suggest, by
making // mean integer division and for / to mean float division.

Try this
0

That's using version 2.3.3
 
M

Michael Neumann

However GvR has decided to fix the problem in the way you suggest, by
making // mean integer division and for / to mean float division.

Try this

0

That's using version 2.3.3

Ah thanks.... would be great to see this in Ruby too (without breaking
existing code).

Regards,

Michael
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: [RCR] Floating point division operator /. (or fdiv method)"

|> Numeric#div does integer division and Numeric#quo does float (or
|> rational if available) division _now_.
|
|Not a good choice of names, IMO, since it's not obvious which is which.
|fdiv is clearer than quo.

Mnemonic: "div" is a 1st value from divmod (i.e. integer division).

matz.
 
M

Martin DeMello

Yukihiro Matsumoto said:
Hi,

In message "Re: [RCR] Floating point division operator /. (or fdiv method)"

|> Numeric#div does integer division and Numeric#quo does float (or
|> rational if available) division _now_.
|
|Not a good choice of names, IMO, since it's not obvious which is which.
|fdiv is clearer than quo.

Mnemonic: "div" is a 1st value from divmod (i.e. integer division).

True, but "quo" means integer to me too (as in "quotient and
remainder"). I liked BASIC's way of doing it - / was floating point and
div was integer, but I guess that wold break code.

martin
 
P

Paul Brannan

you should not be writing anything other people will use.

If you don't like my code, you don't have to use it, but it is not your
place to judge whether I should or should not be writing code for other
people.

Paul
 
B

Bret Jolly

Michael Neumann said:
Ah thanks.... would be great to see this in Ruby too (without breaking
existing code).

It would *not* be great to see this in Ruby: the quotient of two integers
should be a rational, not a float. The behavior given by the mathn library
is the correct one. If the quotient of two rationals is a float, you get
severe errors using the matrix standard library with ill-conditioned matrices.
The Hilbert matrix, which arises in the the theory of least-square fits, is
a good example.

First recall that you *must* require mathn if you use the matrix library.
Here's what happens if you forget:

irb(main):001:0> require 'matrix'
true
irb(main):002:0> m = Matrix[[2, 3], [3, 5]]
Matrix[[2, 3], [3, 5]]
irb(main):003:0> m.det
4 # WRONG
irb(main):004:0> m.inv
Matrix[[0, 0], [-1, 0]] # WRONG
irb(main):005:0> m*m.inv
Matrix[[-3, 0], [-5, 0]] # WRONG: m*m.inv must be the identity matrix
irb(main):006:0> require 'mathn'
true
irb(main):007:0> m.det
1 # correct
irb(main):008:0> m.inv
Matrix[[5, -3], [-3, 2]] # correct
irb(main):009:0> m*m.inv
Matrix[[1, 0], [0, 1]] # correct

Now let's look at what happens if you use float results for integer division.
I define two functions: hilbert and hilbert_float, which create a Hilbert
matrix and its floating-point version, respectively.
# hilbert.rb
# Hilbert matrix of order n
require 'mathn' # ESSENTIAL!

# exact (rational entries)
def hilbert(n)
row_array = []
(1..n).each {|r|
row = []
(r..(n+r-1)).each{|s| row.push(1/s)}
row_array.push(row)
}
Matrix[*row_array]
end

# floating-point entries
def hilbert_float(n)
row_array = []
(1..n).each {|r|
row = []
(r..(n+r-1)).each{|s| row.push((1/s).to_f)}
row_array.push(row)
}
Matrix[*row_array]
end

class Matrix
# find off-diagonal element of maximum magnitude
def biggest_offdiag
biggest = 0
(0...row_size).each {|i|
(0...column_size).each {|j|
if i != j and biggest.abs < self[i, j].abs
biggest = self[i, j]
end
}
}
biggest
end
end
# end of file

A matrix times its inverse is the identity matrix -- 1s on the main
diagonal and 0s elsewhere. So for any invertible matrix m,
(m*m.inv).biggest_offdiag should be 0. Let's try it.
irb(main):001:0> require 'mathn'
true
irb(main):002:0> require 'hilbert'
true
irb(main):003:0> ((m=hilbert(15))*m.inv).biggest_offdiag
0
irb(main):004:0> ((m=hilbert_float(15))*m.inv).biggest_offdiag
-569.0 # INCREDIBLY WRONG!

The quotient of two integers is an exact rational. To make the
quotient default to (inexact) floats can lead to appalling numerical
errors as I have just shown.

Regards, Bret
 
M

Michael Neumann

Michael Neumann said:
Ah thanks.... would be great to see this in Ruby too (without breaking
existing code).

It would *not* be great to see this in Ruby: the quotient of two integers
should be a rational, not a float. The behavior given by the mathn library
is the correct one. If the quotient of two rationals is a float, you get
severe errors using the matrix standard library with ill-conditioned matrices.
The Hilbert matrix, which arises in the the theory of least-square fits, is
a good example.

[...]

irb(main):004:0> ((m=hilbert_float(15))*m.inv).biggest_offdiag
-569.0 # INCREDIBLY WRONG!

The quotient of two integers is an exact rational. To make the
quotient default to (inexact) floats can lead to appalling numerical
errors as I have just shown.

I'm not sure I understand you correctly, or you me. My "suggestion"
was, to make / a floating point division regardless of it's arguments
unless "mathn" is required. But // would always be integer division.

Or to describe it in a little example:

1 / 2 # => 0.5
1 // 2 # => 0

require 'mathn'
1 / 2 # => 1/2

This would break less existing code, as the result of a rational
division compared to a floating point division is more exact, whereas
ration vs. integer division yields very different results (up to 0.5).
Don't get me wrong, now it would break very much code, but if the
applications would use // as integer div, then it would break less code
when they start using mathn.

Regards,

Michael
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top