srand(1); # So everything is using the same numbers my $s = 0; for (1..1000000) { $s += nearest_sqrt(int(rand(2**47))); } print "$s\n"; #### use ntheory qw/divisors/; sub closest { my @d = divisors(shift); $d[ $#d >> 1 ]; } #### use ntheory qw/fordivisors/; sub closest { my($n,$sqrtn,$min) = ($_[0], int(sqrt($_[0]))); fordivisors { $min = $_ if $_ <= $sqrtn; } $n; $min; } #### use ntheory qw/factor/; sub closest { my($n) = @_; my(@factors, @d, @t); # 1. Get list of factors @factors = factor($n); # 2. Turn this into an unsorted list of divisors @d = (1); while (my $p = shift @factors) { my $e = 1; while (@factors && $p == $factors[0]) { $e++; shift(@factors); } push @d, @t = map { $_ * $p } @d; # multiply through once push @d, @t = map { $_ * $p } @t for 2 .. $e; # repeat } # 3. Sort @d = sort {$a<=>$b} @d; # 4. Return the largest divisor <= sqrt n. $d[ $#d >> 1 ]; } #### use Math::Pari qw/divisors/; sub closest { my $d = divisors(shift); $d->[ $#$d >> 1 ]; } #### use Math::Factor::XS qw/factors/; sub closest { my @d = (1, factors($_[0]), $_[0]); $d[ $#d >> 1 ]; }