Bug: Numeric#divmod calculates wrongly

D

Dirk Traulsen

Hi all!

I submitted the following bug report to
http://rubyforge.org/tracker/index.php?func=detail&aid=14540&
group_id=426&atid=1698

===================================================
There is a calculating bug in Numeric#divmod.
The divisor is reproducibly calculated wrongly for certain numbers.

See the following example to illustrate the problem:

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

z1=x.map {|a| a/y}
z2=x.map {|a| a.divmod(y).inspect}

a=[RUBY_VERSION, RUBY_RELEASE_DATE, RUBY_PATCHLEVEL, RUBY_PLATFORM]
puts "ruby #{a[0]} (#{a[1]} patchlevel #{a[2].to_s}) [#{a[3]}]"
puts
print 'x='
p x
puts 'y=1/12.0'
puts
puts "x/y\n---"
puts z1
puts
puts "x.divmod(y)\n-----------"
puts z2


Output:
=================================================
ruby 1.8.6 (2007-03-13 patchlevel 0) [i386-mswin32]

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

x/y
---
6.96
7.08
7.56
7.92
8.04

x.divmod(y)
-----------
[6, 0.08]
[6, 0.00666666666666667]
[6, 0.0466666666666667]
[6, 0.0766666666666667]
[8, 0.00333333333333341]
=================================================

As you can see the divisor 7 is wrongly displayed as 6, while the
modulos are correct.

Dirk Traulsen
 
D

Dirk Traulsen

Am 8 Oct 2007 um 19:49 hat Dirk Traulsen geschrieben:
Output:
=================================================
ruby 1.8.6 (2007-03-13 patchlevel 0) [i386-mswin32] ..
x.divmod(y)
-----------
[6, 0.08]
[6, 0.00666666666666667]
[6, 0.0466666666666667]
[6, 0.0766666666666667]
[8, 0.00333333333333341]
=================================================

As you can see the divisor 7 is wrongly displayed as 6, while the
modulos are correct.

I tested Numeric#divmod on two more systems: SUSE 10.1 and Kubuntu
6.10.
They both run Ruby 1.8.4 and under both systems Numeric#divmod works
correctly!
So this bug was either introduced between Ruby 1.8.4 and 1.8.6 or it is
a problem depending on the OS.

Could somebody please confirm these findings? Especially with other
System and Ruby version combinations this would be really helpful to
nail down this massive bug. A computer should really calculate
correctly...

Dirk Traulsen


The testcode:

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

z1=x.map {|a| a/y}
z2=x.map {|a| a.divmod(y).inspect}

a=[RUBY_VERSION, RUBY_RELEASE_DATE, RUBY_PLATFORM]
puts "ruby #{a[0]} (#{a[1]}) [#{a[2]}]"
puts
print 'x='
p x
puts 'y=1/12.0'
puts
puts "x/y\n---"
puts z1
puts
puts "x.divmod(y)\n-----------"
puts z2


gives under
SUSE 10.1:
===================================================
ruby 1.8.4 (2005-12-24) [i586-linux]

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

x/y
---
6.96
7.08
7.56
7.92
8.04

x.divmod(y)
-----------
[6.0, 0.08]
[7.0, 0.00666666666666667]
[7.0, 0.0466666666666667]
[7.0, 0.0766666666666667]
[8.0, 0.00333333333333341]
===================================================


and Kubuntu 6.10:
===================================================
ruby 1.8.4 (2005-12-24) [i586-linux]

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

x/y
---
6.96
7.08
7.56
7.92
8.04

x.divmod(y)
-----------
[6.0, 0.08]
[7.0, 0.00666666666666667]
[7.0, 0.0466666666666667]
[7.0, 0.0766666666666667]
[8.0, 0.00333333333333341]
===================================================
 
K

Konrad Meyer

--nextPart2732551.RkItB5kZgM
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Quoth Dirk Traulsen:
Am 8 Oct 2007 um 19:49 hat Dirk Traulsen geschrieben:
=20
Output:
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D
ruby 1.8.6 (2007-03-13 patchlevel 0) [i386-mswin32]=20 ..=20
x.divmod(y)
-----------
[6, 0.08]
[6, 0.00666666666666667]
[6, 0.0466666666666667]
[6, 0.0766666666666667]
[8, 0.00333333333333341]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D
=20
As you can see the divisor 7 is wrongly displayed as 6, while the=20
modulos are correct.
=20
=20
I tested Numeric#divmod on two more systems: SUSE 10.1 and Kubuntu=20
6.10.
They both run Ruby 1.8.4 and under both systems Numeric#divmod works=20
correctly!
So this bug was either introduced between Ruby 1.8.4 and 1.8.6 or it is=20
a problem depending on the OS.
=20
Could somebody please confirm these findings? Especially with other=20
System and Ruby version combinations this would be really helpful to=20
nail down this massive bug. A computer should really calculate=20
correctly...
=20
Dirk Traulsen
=20
=20
The testcode:
=20
x=3D[0.58, 0.59, 0.63, 0.66, 0.67]
y=3D1/12.0
=20
z1=3Dx.map {|a| a/y}
z2=3Dx.map {|a| a.divmod(y).inspect}
=20
a=3D[RUBY_VERSION, RUBY_RELEASE_DATE, RUBY_PLATFORM]
puts "ruby #{a[0]} (#{a[1]}) [#{a[2]}]"
puts
print 'x=3D'
p x
puts 'y=3D1/12.0'
puts
puts "x/y\n---"
puts z1
puts
puts "x.divmod(y)\n-----------"
puts z2
=20
=20
gives under
SUSE 10.1:
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D
ruby 1.8.4 (2005-12-24) [i586-linux]
=20
x=3D[0.58, 0.59, 0.63, 0.66, 0.67]
y=3D1/12.0
=20
x/y
---
6.96
7.08
7.56
7.92
8.04
=20
x.divmod(y)
-----------
[6.0, 0.08]
[7.0, 0.00666666666666667]
[7.0, 0.0466666666666667]
[7.0, 0.0766666666666667]
[8.0, 0.00333333333333341]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D
=20
=20
and Kubuntu 6.10:
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D
ruby 1.8.4 (2005-12-24) [i586-linux]
=20
x=3D[0.58, 0.59, 0.63, 0.66, 0.67]
y=3D1/12.0
=20
x/y
---
6.96
7.08
7.56
7.92
8.04
=20
x.divmod(y)
-----------
[6.0, 0.08]
[7.0, 0.00666666666666667]
[7.0, 0.0466666666666667]
[7.0, 0.0766666666666667]
[8.0, 0.00333333333333341]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D

I can't confirm this (incorrect) behaviour.

0.58.divmod(1/12.0) # =3D> [6.0, 0.08]
0.59.divmod(1/12.0) # =3D> [7.0, 0.00666666666666667]

Ruby 1.8.6, Fedora 7.

Regards,
=2D-=20
Konrad Meyer <[email protected]> http://konrad.sobertillnoon.com/

--nextPart2732551.RkItB5kZgM
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)

iD8DBQBHEc0ACHB0oCiR2cwRAmU5AJ9/8CvLhvxWhLnqDFNMRGFZTJoZ9wCfatIW
jwQn2X8iNAzIp3QfsdVPOns=
=fzTC
-----END PGP SIGNATURE-----

--nextPart2732551.RkItB5kZgM--
 
E

Eric Hodel

I tested Numeric#divmod on two more systems: SUSE 10.1 and Kubuntu
6.10.
They both run Ruby 1.8.4 and under both systems Numeric#divmod works
correctly!
So this bug was either introduced between Ruby 1.8.4 and 1.8.6 or
it is
a problem depending on the OS.

Could somebody please confirm these findings? Especially with other
System and Ruby version combinations this would be really helpful to
nail down this massive bug. A computer should really calculate
correctly...

You may want to bring this up on ruby-core (maybe you have? There
was also a documentation patch for divmod, so I may be confused).

I get the same results for 1.8.6 and 1.9.0:

ruby 1.8.6 (2007-09-23) [powerpc-darwin8.10.0]
ruby 1.9.0 (2007-10-13) [powerpc-darwin8.10.0]

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

x/y
---
6.96
7.08
7.56
7.92
8.04

x.divmod(y)
-----------
[6, 0.08]
[6, 0.00666666666666667]
[6, 0.0466666666666667]
[6, 0.0766666666666667]
[8, 0.00333333333333341]
 
A

Alex Shulgin

Could somebody please confirm these findings? Especially with other
System and Ruby version combinations this would be really helpful to
nail down this massive bug. A computer should really calculate
correctly...

It's correct on my system:

Debian lenny (testing)
Linux 2.6.21-2-686 #1 SMP Wed Jul 11 03:53:02 UTC 2007 i686 GNU/Linux

===================================================
ruby 1.8.6 (2007-06-07) [i486-linux]

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

x/y
---
6.96
7.08
7.56
7.92
8.04

x.divmod(y)
-----------
[6, 0.08]
[7, 0.00666666666666667]
[7, 0.0466666666666667]
[7, 0.0766666666666667]
[8, 0.00333333333333341]
===================================================
 
M

M. Edward (Ed) Borasky

Dirk said:
Am 8 Oct 2007 um 19:49 hat Dirk Traulsen geschrieben:
Output:
=================================================
ruby 1.8.6 (2007-03-13 patchlevel 0) [i386-mswin32] ..
x.divmod(y)
-----------
[6, 0.08]
[6, 0.00666666666666667]
[6, 0.0466666666666667]
[6, 0.0766666666666667]
[8, 0.00333333333333341]
=================================================

As you can see the divisor 7 is wrongly displayed as 6, while the
modulos are correct.

I tested Numeric#divmod on two more systems: SUSE 10.1 and Kubuntu
6.10.
They both run Ruby 1.8.4 and under both systems Numeric#divmod works
correctly!
So this bug was either introduced between Ruby 1.8.4 and 1.8.6 or it is
a problem depending on the OS.

Could somebody please confirm these findings? Especially with other
System and Ruby version combinations this would be really helpful to
nail down this massive bug. A computer should really calculate
correctly...

Dirk Traulsen


The testcode:

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

z1=x.map {|a| a/y}
z2=x.map {|a| a.divmod(y).inspect}

a=[RUBY_VERSION, RUBY_RELEASE_DATE, RUBY_PLATFORM]
puts "ruby #{a[0]} (#{a[1]}) [#{a[2]}]"
puts
print 'x='
p x
puts 'y=1/12.0'
puts
puts "x/y\n---"
puts z1
puts
puts "x.divmod(y)\n-----------"
puts z2


gives under
SUSE 10.1:
===================================================
ruby 1.8.4 (2005-12-24) [i586-linux]

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

x/y
---
6.96
7.08
7.56
7.92
8.04

x.divmod(y)
-----------
[6.0, 0.08]
[7.0, 0.00666666666666667]
[7.0, 0.0466666666666667]
[7.0, 0.0766666666666667]
[8.0, 0.00333333333333341]
===================================================


and Kubuntu 6.10:
===================================================
ruby 1.8.4 (2005-12-24) [i586-linux]

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

x/y
---
6.96
7.08
7.56
7.92
8.04

x.divmod(y)
-----------
[6.0, 0.08]
[7.0, 0.00666666666666667]
[7.0, 0.0466666666666667]
[7.0, 0.0766666666666667]
[8.0, 0.00333333333333341]
===================================================

And on Gentoo Linux with ruby-1.8.6-p110-r1

$ ruby divmod-test.rb
ruby 1.8.6 (2007-09-24) [i686-linux]

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

x/y
---
6.96
7.08
7.56
7.92
8.04

x.divmod(y)
-----------
[6, 0.08]
[7, 0.00666666666666667]
[7, 0.0466666666666667]
[7, 0.0766666666666667]
[8, 0.00333333333333341]

If it matters, the hardware is an Athlon Thunderbird and Ruby was
compiled from source, as most of Gentoo is, using gcc 4.2.1 and CFLAGS
"-march athlon-tbird -O2". So ... where is it broken again?

Dirk says "ruby 1.8.6 (2007-03-13 patchlevel 0) [i386-mswin32] is broken"
Dirk says "Kubuntu 6.10 and SuSE 10.1 using Ruby 1.8.4 works."
Konrad says "two test cases worked on Fedora 7 with 1.8.6"
And I have it working on Ruby 1.8.6-p110 on Gentoo, compiled from source
with GCC 4.2.1
And Eric has it broken on PowerPC Macs for both Ruby 1.8.6 and Ruby 1.9.0

Eric, what compiler made the Ruby interpreters on your PowerPC?

And everybody -- recompile ruby-1.8.6-p111 and see whether it works or
not. I say it's a compiler problem at this point -- maybe
over-aggressive floating-point optimization?? I doubt if the Ruby source
is broken.
 
D

Dirk Traulsen

Hi Eric!

Am 14 Oct 2007 um 17:03 hat Eric Hodel geschrieben:
You may want to bring this up on ruby-core (maybe you have? There
was also a documentation patch for divmod, so I may be confused).

I took your advice and send a mail to ruby-core.

The documentation patch, which is also from me, is for the
same method, but unrelated.

Thanks for testing.

Dirk
 
B

Brian Adkins

Ubuntu 7.04
Linux imagine 2.6.20-16-generic #2 SMP Sun Sep 23 19:50:39 UTC 2007
i686 GNU/Linux

ruby 1.8.5 (2006-08-25) [i486-linux]

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

x/y
---
6.96
7.08
7.56
7.92
8.04

x.divmod(y)
-----------
[6, 0.08]
[7, 0.00666666666666667]
[7, 0.0466666666666667]
[7, 0.0766666666666667]
[8, 0.00333333333333341]
 
E

Eric Hodel

And Eric has it broken on PowerPC Macs for both Ruby 1.8.6 and Ruby
1.9.0

Eric, what compiler made the Ruby interpreters on your PowerPC?

And everybody -- recompile ruby-1.8.6-p111 and see whether it works
or not. I say it's a compiler problem at this point -- maybe over-
aggressive floating-point optimization?? I doubt if the Ruby source
is broken.

$ gcc -v
[...]
gcc version 4.0.1 (Apple Computer, Inc. build 5367)
$ ruby19 -v -rrbconfig -e 'p Config::CONFIG["CFLAGS"]'
ruby 1.9.0 (2007-10-13 patchlevel 0) [powerpc-darwin8.10.0]
"-g -O2 -pipe -fno-common"
$ ruby18 -v -rrbconfig -e 'p Config::CONFIG["CFLAGS"]'
ruby 1.8.6 (2007-09-23 patchlevel 5000) [powerpc-darwin8.10.0]
"-g -O2 -fno-schedule-insns2 -pipe -fno-common"

-fno-schedule-insns2 is to work around a GCC bug.
 
M

M. Edward (Ed) Borasky

Eric said:
And Eric has it broken on PowerPC Macs for both Ruby 1.8.6 and Ruby 1.9.0

Eric, what compiler made the Ruby interpreters on your PowerPC?

And everybody -- recompile ruby-1.8.6-p111 and see whether it works or
not. I say it's a compiler problem at this point -- maybe
over-aggressive floating-point optimization?? I doubt if the Ruby
source is broken.

$ gcc -v
[...]
gcc version 4.0.1 (Apple Computer, Inc. build 5367)
$ ruby19 -v -rrbconfig -e 'p Config::CONFIG["CFLAGS"]'
ruby 1.9.0 (2007-10-13 patchlevel 0) [powerpc-darwin8.10.0]
"-g -O2 -pipe -fno-common"
$ ruby18 -v -rrbconfig -e 'p Config::CONFIG["CFLAGS"]'
ruby 1.8.6 (2007-09-23 patchlevel 5000) [powerpc-darwin8.10.0]
"-g -O2 -fno-schedule-insns2 -pipe -fno-common"

-fno-schedule-insns2 is to work around a GCC bug.

As an aside, I downloaded "paranoia"
(http://netlib2.cs.utk.edu/paranoia/paranoia.c) and ELEFUNT
(http://www.math.utah.edu/pub/elefunt/elefunt.tar.gz) and ran them with
gcc 4.2.2 on my Athlon64. "paranoia" tests the basic floating point
hardware, and ELEFUNT tests the math libraries. I'm satisfied from those
tests that gcc is "doing the right thing".

An exercise to the student would be to port these two test suites to
Ruby and see how well they do. But relative to the bug in question, I
ran the divmod.rb with all optimization turned off on the Athlon64 using
gcc 4.2.2 and it's broken.

I took a look at "numeric.c" in Ruby 1.8.6-p111 to see what "divmod" is
actually doing. I was somewhat disturbed by the complicated path that it
takes to get its answer, and in thinking about the function itself, I
wonder what its usefulness is, given the willy-nilly way it flits
between integer and floating point arithmetic. And it's essentially
doing "divmod" by doing a "div" and a "mod", so there's no efficiency
gain, unlike what you'd have in the integer case where you do a divide
and get the remainder for free, at least at the hardware level.

Does the original poster have an actual use case for "divmod" in its
present definition? I couldn't think of any use for it in its present
definition. What I would find useful would be something that took a
Bignum dividend and divisor and returned the Bignum quotient and remainder.
 
R

Rick DeNatale

I don't believe that anyone has brought up the intel Macs as yet, but
I get the same results as the OP on my MacBook:
ruby 1.8.6 (2007-03-13 patchlevel 0) [i686-darwin8.10.2]

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

x/y
---
6.96
7.08
7.56
7.92
8.04

x.divmod(y)
-----------
[6, 0.08]
[6, 0.00666666666666667]
[6, 0.0466666666666667]
[6, 0.0766666666666667]
[8, 0.00333333333333341]


I've already added this as a comment to the trac report.
 
A

Axel Etzold

Just for the records: (Suse 10.2 , Ruby compiled with
with gcc version 4.1.2 20061115 (prerelease) (SUSE Linux)


ruby 1.8.6 (2007-03-13) [x86_64-linux]

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

x/y
---
6.96
7.08
7.56
7.92
8.04

x.divmod(y)
-----------
[6, 0.08]
[6, 0.00666666666666667]
[6, 0.0466666666666667]
[6, 0.0766666666666667]
[8, 0.00333333333333341]
 

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

Similar Threads


Members online

Forum statistics

Threads
473,968
Messages
2,570,153
Members
46,699
Latest member
AnneRosen

Latest Threads

Top