[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Bug: Numeric#divmod calculates wrongly

Dirk Traulsen

10/8/2007 10:50:00 AM

Hi all!

I submitted the following bug report to
http://rubyforge.org/tracker/index.php?func=detail&aid=...
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


13 Answers

Dirk Traulsen

10/14/2007 7:19:00 AM

0

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]
===================================================


Konrad Meyer

10/14/2007 8:02:00 AM

0

Quoth 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]
> ===================================================

I can't confirm this (incorrect) behaviour.

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

Ruby 1.8.6, Fedora 7.

Regards,
--
Konrad Meyer <konrad@tylerc.org> http://konrad.sobertil...

Eric Hodel

10/14/2007 8:03:00 AM

0

On Oct 14, 2007, at 24:18 , Dirk Traulsen wrote:
> 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]


--
Poor workers blame their tools. Good workers build better tools. The
best workers get their tools to do the work for them. -- Syndicate Wars



Alex Shulgin

10/14/2007 9:15:00 AM

0

On Oct 14, 10:18 am, "Dirk Traulsen" <dirk.traul...@lypso.de> wrote:
>
> 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]
===================================================

--
Cheers,
Alex

M. Edward (Ed) Borasky

10/14/2007 10:45:00 AM

0

Dirk Traulsen wrote:
> 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.

Dirk Traulsen

10/14/2007 11:34:00 AM

0

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

Carl Johnson

10/14/2007 6:13:00 PM

0

"Dirk Traulsen" <dirk.traulsen@lypso.de> writes:

> 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.
> >
>
>
>
> 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

Mine has the same problem running on an Athlon64 running on Debian's
AMD64 version of Etch:

ruby 1.8.5 (2006-08-25) [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]

--
Carl Johnson carlj@peak.org

Brian Adkins

10/14/2007 7:32:00 PM

0

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]

Eric Hodel

10/14/2007 8:26:00 PM

0

On Oct 14, 2007, at 03:44 , M. Edward (Ed) Borasky wrote:

> 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.

--
Poor workers blame their tools. Good workers build better tools. The
best workers get their tools to do the work for them. -- Syndicate Wars



M. Edward (Ed) Borasky

10/14/2007 8:56:00 PM

0

Eric Hodel wrote:
> On Oct 14, 2007, at 03:44 , M. Edward (Ed) Borasky wrote:
>
>> 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.
>
> --
> Poor workers blame their tools. Good workers build better tools. The
> best workers get their tools to do the work for them. -- Syndicate Wars
>
>
>
>

As an aside, I downloaded "paranoia"
(http://netlib2.cs.utk.edu/paranoia/...) and ELEFUNT
(http://www.math.utah.edu/pub/elefunt/elef...) 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.