Skip Menu |

This queue is for tickets about the Math-Factor-XS CPAN distribution.

Report information
The Basics
Id: 84301
Status: open
Priority: 0/
Queue: Math-Factor-XS

People
Owner: Nobody in particular
Requestors: bkb [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 0.40
Fixed in: (no value)



Subject: Unexpected behaviour with floating point errors
The output of the following test is surprising: #!/home/ben/software/install/bin/perl use warnings; use strict; use Test::More; use Math::Factor::XS ':all'; my @p = (0.7, 0.1); my @q; for my $x (@p) { for my $y (@p) { push @q, $x * $y; } } my @r = map {$_ * 100} @q; print "\@r = @r\n"; for my $r (@r) { my @factors = prime_factors ($r); if ($r == 7) { is (scalar @factors, 1); is_deeply (\@factors, [7]); } else { print $r - 7, "\n"; print "$r -> @factors\n"; } } done_testing (); Output follows: @r = 49 7 7 1 42 49 -> 2 2 2 2 3 -8.88178419700125e-16 7 -> 2 3 -8.88178419700125e-16 7 -> 2 3 -6 1 -> 1..0 # No tests run! What Perl prints as "7" is taken to be 6 by the module and factorized as "2 3". The difference between the value 7 and the actual value is a tiny floating point error. I would suggest that either the module should round the number to the nearest integer, or simply refuse to process a non-integer value.
This adds a test file, uses "round" to fix the bug in "prime_factors". https://github.com/benkasminbullock/Math-Factor-XS/commit/3121550ebd15c5271218b8c1c3b79f34e5ce2422 I have also added the tests for this one: https://github.com/benkasminbullock/Math-Factor-XS/commit/dd791dbd8206c4326fab9c961c4fbaac48dcf36f This is one way to fix the bug. I tried another way using SvNOK and friends but this did not work for me, so the above crude method is the one I settled on.
On Fri Mar 29 23:48:01 2013, BKB wrote: Show quoted text
> I have also added the tests for this one:
Sorry, this message is in error. It should read "I have also added the same functioning (using "round" from the C maths library) to round off the input "number" for the other two routines in XS.xs".
Show quoted text
> I would suggest that either the module should round the number to the > nearest integer,
Math::Factor::XS uses SvUV via the typemap to get its desired integer, and that has the effect of rounding towards 0. Almost everything in perl which wants an integer uses SvUV that way. Show quoted text
> or simply refuse to process a non-integer value.
Perhaps, since it doesn't make much sense to factorize a non-integer. The only thing I'd be a little wary of is attempting to have a lone module like Math::Factor::XS do anything too fancy about ints versus floats. Does anywhere else notice and reject non-integers? There's a great deal of slackness in perl between integers and floats. Sometimes it's quite convenient, if the rounding goes the way you want :-).
Subject: Re: [rt.cpan.org #84301] Unexpected behaviour with floating point errors
Date: Tue, 2 Apr 2013 08:56:05 +0900
To: bug-Math-Factor-XS [...] rt.cpan.org
From: Ben Bullock <benkasminbullock [...] gmail.com>
On 2 April 2013 08:45, Kevin Ryde via RT <bug-Math-Factor-XS@rt.cpan.org>wrote: Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=84301 > >
> > I would suggest that either the module should round the number to the > > nearest integer,
> > Math::Factor::XS uses SvUV via the typemap to get its desired integer, and > that has the effect of rounding towards 0. Almost everything in perl which > wants an integer uses SvUV that way. >
It doesn't round to 0 though. Did you look at my example? It is given 007 * 100 and then factorizes it into 3 and 2. That's not rounding of any kind, it is truncating the floating point. Show quoted text
> > or simply refuse to process a non-integer value.
> > Perhaps, since it doesn't make much sense to factorize a non-integer. The > only thing I'd be a little wary of is attempting to have a lone module like > Math::Factor::XS do anything too fancy about ints versus floats. Does > anywhere else notice and reject non-integers? >
I don't know. Show quoted text
> There's a great deal of slackness in perl between integers and floats. > Sometimes it's quite convenient, if the rounding goes the way you want :-). > >
On Mon Apr 01 19:56:20 2013, benkasminbullock@gmail.com wrote: Show quoted text
> > Did you look at my example?
Yes. Show quoted text
> It is given 007 * 100 and then factorizes it into 3 and 2.
0.7 * 0.1 * 100 gives for me 6.99999999999999911182, when printed with "%.20f", and which rounds towards zero to factorize as 6 = 2*3. Similarly the 0.7 * 0.7 * 100 as 48.99999999999999289457 factorizing 48 = 2 2 2 2 3. I believe neither 0.1 nor 0.7 are exactly representable in binary, so both lose exactness.
Subject: Re: [rt.cpan.org #84301] Unexpected behaviour with floating point errors
Date: Fri, 5 Apr 2013 11:07:33 +0900
To: bug-Math-Factor-XS [...] rt.cpan.org
From: Ben Bullock <benkasminbullock [...] gmail.com>
I was able to confirm that this is what Perl does: ---------------------- use warnings; use strict; my $y = 0.1; my $x = 0.7; $x *= $y; $x *= 100; printf ("%.100g\n", $x); printf ("%g\n", $x); for my $f (1..7) { if ($x % $f == 0) { print "$f ok\n"; } } --------------- 6.99999999999999911182158029987476766109466552734375 7 1 ok 2 ok 3 ok 6 ok -------------- It's really up to you what you think it should do. I find this default rather bizarre but that is apparently the "Perl way of doing things". On 5 April 2013 06:05, Kevin Ryde via RT <bug-Math-Factor-XS@rt.cpan.org> wrote: Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=84301 > > > On Mon Apr 01 19:56:20 2013, benkasminbullock@gmail.com wrote:
>> >> Did you look at my example?
> > Yes. >
>> It is given 007 * 100 and then factorizes it into 3 and 2.
> > 0.7 * 0.1 * 100 gives for me 6.99999999999999911182, when printed with "%.20f", and which rounds towards zero to factorize as 6 = 2*3. Similarly the 0.7 * 0.7 * 100 as > 48.99999999999999289457 factorizing 48 = 2 2 2 2 3. > > I believe neither 0.1 nor 0.7 are exactly representable in binary, so both lose exactness.