问题
I have several questions with the following algorithms to tell if a number is prime, I also know that with the sieve of Eratosthenes can be faster response.
- Why is faster to compute
i i * sqrt (n)
times. thansqrt (n)
just one time ? - Why
Math.sqrt()
is faster than mysqrt()
method ? What is the complexity of these algorithms O (n), O (sqrt (n)), O (n log (n))?
public class Main { public static void main(String[] args) { // Case 1 comparing Algorithms long startTime = System.currentTimeMillis(); // Start Time for (int i = 2; i <= 100000; ++i) { if (isPrime1(i)) continue; } long stopTime = System.currentTimeMillis(); // End Time System.out.printf("Duracion: %4d ms. while (i*i <= N) Algorithm\n", stopTime - startTime); // Case 2 comparing Algorithms startTime = System.currentTimeMillis(); for (int i = 2; i <= 100000; ++i) { if (isPrime2(i)) continue; } stopTime = System.currentTimeMillis(); System.out.printf("Duracion: %4d ms. while (i <= sqrt(N)) Algorithm\n", stopTime - startTime); // Case 3 comparing Algorithms startTime = System.currentTimeMillis(); for (int i = 2; i <= 100000; ++i) { if (isPrime3(i)) continue; } stopTime = System.currentTimeMillis(); System.out.printf( "Duracion: %4d ms. s = sqrt(N) while (i <= s) Algorithm\n", stopTime - startTime); // Case 4 comparing Algorithms startTime = System.currentTimeMillis(); for (int i = 2; i <= 100000; ++i) { if (isPrime4(i)) continue; } stopTime = System.currentTimeMillis(); System.out.printf( "Duracion: %4d ms. s = Math.sqrt(N) while (i <= s) Algorithm\n", stopTime - startTime); } public static boolean isPrime1(int n) { for (long i = 2; i * i <= n; i++) { if (n % i == 0) return false; } return true; } public static boolean isPrime2(int n) { for (long i = 2; i <= sqrt(n); i++) { if (n % i == 0) return false; } return true; } public static boolean isPrime3(int n) { double s = sqrt(n); for (long i = 2; i <= s; i++) { if (n % i == 0) return false; } return true; } public static boolean isPrime4(int n) { // Proving wich if faster between my sqrt method or Java's sqrt double s = Math.sqrt(n); for (long i = 2; i <= s; i++) { if (n % i == 0) return false; } return true; } public static double abs(double n) { return n < 0 ? -n : n; } public static double sqrt(double n) { // Newton's method, from book Algorithms 4th edition by Robert Sedgwick // and Kevin Wayne if (n < 0) return Double.NaN; double err = 1e-15; double p = n; while (abs(p - n / p) > err * n) p = (p + n / p) / 2.0; return p; } }
This is the link of my code also: http://ideone.com/Fapj1P
回答1:
1. Why is faster to compute i*i, sqrt (n) times. than sqrt (n) just one time ?
Look at the complexities below. The additional cost of computing square root.
2. Why Math.sqrt() is faster than my sqrt() method ?
Math.sqrt() delegates call to StrictMath.sqrt which is done in hardware or native code.
3. What is the complexity of these algorithms?
The complexity of each function you described
i=2 .. i*i<n
O(sqrt(n))
i=2 .. sqrt(n)
O(sqrt(n)*log(n))
i=2 .. sqrt (by Newton's method)
O(sqrt(n)) + O(log(n))
i=2 .. sqrt (by Math.sqrt)
O(sqrt(n))
Newton's method's complexity from
http://en.citizendium.org/wiki/Newton%27s_method#Computational_complexity
回答2:
Squaring a number is effectively an integer operation while sqrt is floating point. Recognizing the run-time allocations for casting and computation the results you have observed are not surprising.
The Wikipedia page on sqrt http://en.wikipedia.org/wiki/Square_root has a nice section on computation.
As for the faster method I trust you can investigate (sub)linear run-time operation n^2.
On the note of run-times you might like this little piece of code I wrote up to demonstrate the number of system calls made to functions during iteration, you may find it, or something similar to it in java useful as you think about this sort of stuff. gist.github.com/Krewn/1ea0c788ac7210efc475
edit: Here is a nice explanation of integer sqrt. run-times http://www.codecodex.com/wiki/Calculate_an_integer_square_root
edit: on a 64 nm core2 to--- How slow (how many cycles) is calculating a square root?
Please include output in your post when possible Related to your question although approaching primes in a different way,
def getPrimes(n):
primes = [2]
# instantiates our list to a list of one element, 2
k = 3
while(len(primes) < n):
# python uses the prefix function len(var) for lists dictionaries and strings
k2 = 0
isprime=True
#Vacuously true assumption that every number is prime unless
while(primes[k2]**2<=k): # <> this is where you are substituting sqrt with sq <> #
if(k%primes[k2]==0):
isprime=False
break
k2+=1
if(isprime):primes.append(k)
k+=2
return(primes)
print (getPrimes(30))
来源:https://stackoverflow.com/questions/27112162/why-is-multiplied-many-times-faster-than-taking-the-square-root