P is for Practical PerlMonks

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

by sleepingsquirrel (Hermit)
 on Feb 20, 2005 at 01:00 UTC ( #432807=note: print w/replies, xml ) Need Help??

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

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

Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://432807]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (4)
As of 2022-08-17 00:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?

No recent polls found

Notices?