Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Re^2: OT: Finding Factor Closest To Square Root

by Limbic~Region (Chancellor)
on Feb 27, 2005 at 21:16 UTC ( [id://434928]=note: print w/replies, xml ) Need Help??


in reply to Re: OT: Finding Factor Closest To Square Root
in thread OT: Finding Factor Closest To Square Root

Roy Johnson,
Here it is, fast and accurate.

Well it is certainly fast, but unfortunately it is not always accurate. Try (3, 5, 16381, 77951) - it should produce 81905 but it produces 77951. I didn't bother debugging as I was gathering statistics.

Cheers - L~R

Replies are listed 'Best First'.
Re^3: OT: Finding Factor Closest To Square Root
by Roy Johnson (Monsignor) on Feb 28, 2005 at 15:01 UTC
    You're right. I had an erroneous understanding: that the closest factor that included top_factor would be paired with the closest factor that didn't. Instead, it's paired with the closest factor on the other side of root that doesn't include top_factor. So you have to check both sides of root. Here's a fixed version:
    use strict; use warnings; use List::Util qw[ reduce ]; my $num; # Used in sub, but could be passed if you wanted sub closest { # Args are target and factor-list my ($target, @factors) = @_; # Take the biggest factor my $top_factor = pop @factors; # Find multiple of that factor closest to (and above) target my $guess = int($target) - $target % $top_factor + $top_factor; # Oscillate around the target, looking at multiples of top_factor # until you get one that divides the product my $i; for ($i = $top_factor; $num % $guess; $i += $top_factor) { $guess += ( $target <=> $guess ) * $i; } # Check the complementary factor my $complement = $num / $guess; # Look for a multiple of $top_factor between the last guess on the # other side of sqrt and $complement my $direction = ($target <=> $guess); my $new_guess = $guess + $direction * $i; while (($complement <=> $new_guess) == $direction and $num % $new_ +guess) { $new_guess += $top_factor * $direction; } if ($new_guess and $num % $new_guess == 0 and (($complement <=> $new_guess) == $direction)) { $guess = $new_guess; $complement = $num/ $guess; } abs($target - $complement) < abs($target - $guess) ? $complement : $guess ; } my @pfs = (3, 5, 16381, 77951); # Compute product of factors our ($a, $b); $num = reduce { $a * $b } @pfs; my $root = sqrt $num; print "N=$num, R=$root\n"; print closest($root, 1, @pfs), "\n";

    Caution: Contents may have been coded under pressure.
      Roy Johnson,
      What am I missing - it still produces 77951 as the answer?

      Cheers - L~R

        I fixed a different bug and re-broke this! Ok, it's updated and works at least for your example. Gotta update my benchmark code, too.

        Caution: Contents may have been coded under pressure.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://434928]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (2)
As of 2024-04-26 03:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found