http://qs1969.pair.com?node_id=432807


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

Do you really have to do a search for numbers greater than the sqrt(N)? (See Re: OT: Finding Factor Closest To Square Root for my approach). Certainly you don't have to go beyond 2*sqrt(N) on the ++ side. In fact I'm currently thinking the closest factor has to be less than sqrt(N), eliminating any checking for factors greater than sqrt(N). I'd be interested to see if someone could construct a counter-example (a number where the closest factor to sqrt(N) is greater than sqrt(N)).


-- All code is 100% tested and functional unless otherwise noted.
  • Comment on Re^2: OT: Finding Factor Closest To Square Root

Replies are listed 'Best First'.
Re^3: OT: Finding Factor Closest To Square Root
by BrowserUk (Patriarch) on Feb 20, 2005 at 02:22 UTC
    Do you really have to do a search for numbers greater than the sqrt(N)?

    You right. And now you pointed it out, it seems fairly obvious:

    3600: sqrt=60; 59* 61= 3599

    10000: sqrt=100; 99*101= 9999

    12: sqrt=3.464; 3* 4= 12

    Which, in very non-technical terms because my memory doesn't go back to my formal math days, says to me that:

    with lo = int( sqrt( N ) ) & hi = int( sqrt( n ) )+1; lo * hi is always less than or equal to N.

    If you reduce lo, leaving hi the same, you get further away from N. And if you increase hi, lo will be nearer.

    Does that form an explaination? Hmm. Maybe one of our resident math whiz can phrase that correctly?


    Examine what is said, not who speaks.
    Silence betokens consent.
    Love the truth but pardon error.
      Here's an informal proof of our conjecture "The factor of N closest to sqrt(N) is less than sqrt(N)".
      1. Let M be the positive square root of N. (M*M = N, M>0)
      2. The closest factor to M is bewteen 1 and 2*M. (i.e. 1 is closer to M than any number greater than twice M. (M-1 < 2*M-M))
      3. For every pair of numbers whose product is N, one of the pair will be greater than M and the other less than M. (the product of two numbers greater than M is greater than N, and the product of two numbers less than M would be less than N)
      4. Take a pair of numbers whose product is N. Call the smaller (M-X) and the larger (M+Y). (i.e. X>0, Y>0)
      5. So, (M-X) * (M+Y) = N
      6. Multiplying out, M^2 + M*(Y-X) - X*Y = N
      7. But M^2 = N (by definition)
      8. Substituting: N + M*(Y-X) - X*Y = N
      9. Subtracting N: M*(Y-X) - X*Y = 0
      10. Since X and Y are positive (by definition, step 4), the term -X*Y is negative
      11. If -X*Y is negative, the only way for the entire sum to equal 0 is if the term M*(Y-X) is positive
      12. But M is positive (step 1), so (Y-X) must also be positive, which means that Y is greater than X.
      13. Finally, if Y is greater than X, the smaller factor, (M-X) is closer to M than (M+Y), so you can limit your factor search to numbers less than sqrt(N).


      -- All code is 100% tested and functional unless otherwise noted.

        Here's an easier way: take n = m^2, and a factor greater than the square root m + d, then the other factor is:

        m^2/(m + d) = m - dm/(m + d) = m - d + d^2/(m + d)
        Now d^2/(m + d) is greater than zero, so the cofactor is greater than m - d and hence closer to the square root.

        Hugo

        sleepingsquirrel++

        Makes sense to me--but then my version did (to me) too :)

        Who'd've thunk it--even informality is relative :)

Re^3: OT: Finding Factor Closest To Square Root
by BrowserUk (Patriarch) on Feb 20, 2005 at 02:39 UTC
    Certainly you don't have to go beyond 2*sqrt(N) on the ++ side

    The high side search would always have terminated there or earlier anyway as it stopped as soon as the difference between it and the root was greater than that between lo and root. Lo can't go below 1, so hi would never go above root*2-1. But skipping the hi search is much better.

    Another optimisation possible if N is odd, is to step back by 2 each time.


    Examine what is said, not who speaks.
    Silence betokens consent.
    Love the truth but pardon error.
      Another optimisation possible if N is odd, is to step back by 2 each time.
      And if N is even, factor out all the powers of 2, and run the algorithm against the remaining factor. For example,
      1000 == 2**3 * 5**3
      which leaves
      125 == 5**3
      leading to
      5 * 2**2 == 20
      as "close enough".

      -QM
      --
      Quantum Mechanics: The dreams stuff is made of

        I moved away from using M::B::F. The "best" I came up with is:

        #! perl -slw use strict; my $NUM = $ARGV[ 0 ] || die 'No arg'; $NUM = eval $NUM if $NUM =~ m[\D]; my $root = sqrt( $NUM ); my $near = int $root; my $step = $NUM % 2 ? 2 : 1; $near-= $step while $near and $NUM % $near; $near = 1 unless $near; printf "%10.f (%10f) %.f\n", $NUM, $root, $near;

        It's a simple brute force search for a factor < root.

        There may be a way to use the prime factors to speed the search, but the time they take to produce, a linear search down from the root is quicker.

        Even with a largish prime like 988041964007, which means a linear search all the way to 1, this takes less than a second, where Math::Big::Factors::Factors_wheel() churns for hours trying to factorise it.

        Maybe there's a qucker factorising module out there somewhere? Even so, from what I've tried and seen from other peoples attempts, having the prime factors doesn't give you any obvious way to avoid what amounts to a linear search.


        Examine what is said, not who speaks.
        Silence betokens consent.
        Love the truth but pardon error.