Java Prime Factorization: Program timing out? - java

Before I get blasted for not following the rules, I DID utilize the search function and see that there are multiple threads on this exact problem. However, none of them answered my specific question.
I'm working on Euler problem #3, where I need to find the highest prime factor of 600851475143. I don't need help solving the problem. I have made a brute force method (could be better, I know) for solving it.
The program returns correctly for all of the tests that I did with smaller numbers (7 digits and less). However, when I enter 600851475143 as a long input, my program never gives me a return. Is my number simply too big the be entered? What could be causing this to happen? I originally thought it was because I was using int tags instead of long, but changing those didn't alter my result.
I'm sure this is simple and I'm missing it, but I am very curious as to what's happening. Thank you in advance :)
//Euler 3: Largest Prime Factor
import java.io.*;
import java.util.Scanner;
import java.lang.Math;
public class Euler3
{
public static void main(String[] args)
{
Scanner scn = new Scanner(System.in);
System.out.println("Enter a number!");
// Create scanner
long numberInput=scn.nextLong();
//Can't have a factor higher than it's square root
double limit=Math.floor(Math.sqrt(numberInput));
// System.out.println(limit);
//Start testing from the highest number possible
for(long i=(numberInput-1);i>0; i--)
{
if(numberInput%i==0)
System.out.println(i+" is prime: "+isPrime(i));
}
} //End Main
public static boolean isPrime(long n)
{
//check if n is a multiple of 2
if (n%2==0) return false;
//if not, then just check the odds
for(int i=3;i*i<=n;i+=2)
{
if(n%i==0)
return false;
}
return true;
}
}

To verify if a number is Prime or not, use the Sieve of Eratosthenes, it will run much faster compared to your naive isPrime method. I won't provide any implementation hint due to this phrase: I don't need help solving the problem.
Also, there could be other hints that you missed. I recommend you to review the problem statement:
What is the largest prime factor

A long variable can easily fit your desired value into it
long: The long data type is a 64-bit signed two's complement integer. It has a minimum value of -9,223,372,036,854,775,808 and a maximum value of 9,223,372,036,854,775,807 (inclusive). Use this data type when you need a range of values wider than those provided by int.
The problem is that your algorithm is not an efficient one. As has already been mentioned, use the Sieve of Eratosthenes

The problem is not in the isPrime method but in the loop you use to call it. You count down from your number n with increments of 1, and you call isPrime only for divisors of n: it will take n/2 steps before you get to the first potential divisor of n - so, in the order of 10^12 steps for your example n.

Related

Enter 100 numbers. Determine which number is more: positive or negative

so i have this homework where i have to enter 100 numbers and after that it determines if its positive or negative, been trying for hours but still unsuccesful.
Enter 100 numbers. Determine which number is more: positive or negative. (This is literally the task and nothing more is written)
When approaching a problem, first think it thru. Then write the code.
initialize a positive or negative counter.
start reading in numbers
increment the counter based on the number's sign.
continue with (2) until 100 numbers have been read.
Print out informative information based on the results of the contents of (1) and the count of numbers read.
If you are just trying to find the highest magnitude of either positive or negative numbers you can do this quite easily by checking the absolute value:
import java.util.concurrent.ThreadLocalRandom;
public class MyClass
{
public static void main(String args[])
{
int randomNum = 0;
int largestMagnitude = 0;
for(int i = 0; i < 100; i++)
{
randomNum = ThreadLocalRandom.current().nextInt(-1000, 1000);
if(Math.abs(randomNum) > Math.abs(largestMagnitude))
{
largestMagnitude = randomNum;
}
}
System.out.println("The highest magnitude of number generated was " + largestMagnitude);
}
}
This is an suggestion to people providing answers. When the problem is a homework (as the OP CLEARLY indicated) it is important to ask what are they currently learning in order to properly frame the answer to the lesson. Basically, the most correct answer for industry might not (and often it is not) the most correct answer for what it is being taught.
#Janis Klein, what you are covering in class at the moment is very important. For example, if you are learning about sorting, the answer might be to implement some sort of sorting algorithm. When you sort a collection of numbers, the most negative and the most positive will be the head and tail values in your sorted collection. If you are learning about lists and collections, the answer might be to implement some sort of linked list where the numbers are inserted in natural order (no need to sort). Like in my previous example, once you insert all 100 values into this list, the head and tail values are the most positive and negative values.
However, if all you are learning is to do comparisons of values, you don't need but two variables (one for most positive and one for most negative) and all you will need to do is to compare incoming values and store them into the correct variable if needed. For example, the very first value will be both the most positive and most negative. The second incoming value will be either the most positive or most negative (assuming unique values are always received). From the third value on, the incoming value MIGHT be the most positive, the most negative, or simply neither; in which case, the incoming value is discarded. In the end, the most negative and most positive values will be the values stored in the respective variables.
Again, the scope of the answer MUST be framed based on what you are currently learning in class.

Determining the worst case running time (prime numbers)

I need help.
I have a method which determines if a int is a prime:
public boolean isPrime(int n) {
if (n % 2 == 0) {
return false;
}
for (int i = 3; i < n; i += 2) {
if (n % i == 0) {
return false;
}
}
return true;
}
Could anyone tell me how to determine the worst case time running of this program?
Then let B equal the number of bits in the binary representation of N ... what would be the worst case time running in terms of B?
Thanks! :)
The running-time of this function is O(n) in every case though in fact the worst case will only come up if n is really a prime number.
Also, if you want to detect all primes in a range from for examle 1 until n, your runtime will be O(n^2).
The asymptotic time complexity of your prime number calculator is O(n). There is no reason to incorporate "B" into the calculation of time complexity in this case.
Well at firs glans it seams it will take O(n) but there is an issue here if n=Integer.MaxValue which is equals to 2147483647 at some point you will reach 2147483645 then when adding 2 i will become 2147483647 and in next addition it will become -2147483647 so you have sciped to negative numbers so that may take a while .
Your function incorrectly states that 2 is not a prime number. The third line that currently reads return false should read return (n == 2) or whatever the proper syntax for that is in Java.
Running time for the algorithm is O(n), which will occur whenever n is prime. You could improve the run time to O(sqrt n) by changing the test in the for loop to i * i <= n.
The snarky response is to say that it finishes in O(1), because n is bounded above by a 2^31-1 in Java. Hence, I can find a single constant K such that the time is guaranteed to finish in less than that time K.
However, this response does not address what is intended by your question, which is, how the time differs as a function of n within a "reasonable" range for n. As others have pointed out already, your running time will be O(n).
In terms of B, there's a potential bit of confusion, because the integers are always represented with a 32-bit signed integer. However, if we ask how many bits are required at maximum for a given value of N, we can note that 2^B < N <= 2^(B+1), so if your calculation requires O(n), it would necessarily require O(2^B) operations.
Also, as others have pointed out, there's an error condition for the value 2 - easily fixable. In addition, this calculation could be easily improved using Sieve methods. While you did not really ask about optimization, I provide the service free of charge. :) See: https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes for an interesting approach to addressing this problem. And believe it or not, this is really just the beginning of optimizing this. There are many more things you can do from there.

How to solve the non-negative subset sum using recursion in Java?

I am really confused by a question that says:
Given a set of non-negative integers, and a value sum, the goal is to identify all subsets whose sum of elements is equal to sum. For example, if the set of non-negative integers is {3; 34; 4; 12; 5; 2} and sum = 9, then answer is {4; 5} and {4; 2; 3}.
This question must be solved through a recursive method (one recursion function and one main string[]args function) but I have no idea on how to make it. Can someone give a hint?
Seeing you asked for a hint rather than code, I'll give you a pointer on algorithm to get you started.
Generally recursive algorithms look something like:
recursiveFunction(currentResult, context)
if currentResult satisfies given condition
process currentResult
for each possibleResult in context
recursiveFunction(possibleResult, contextWithResultRemoved)
In your case the signature of the method will be something like:
public void allSubsetsWithSum(int targetSum, Set<Integer> current, Set<Integer> remaining)
The satisfying condition test just compares the sum of current to the target.
The 'for each' would just look at each integer in remaining and move it to current before recursing.
There are efficiency shortcuts such as not processing integers from remaining that will make the sum exceed your target. But that isn't necessary to make the algorithm to work.
Hopefully that will get you started. Ask further questions if you don't understand the hints.

Factorial calculation

I'm studying java programming by going through Computer Science at the Saylor academy's webpage. I got to the point where I'm learning about debugging programs in NetBeans, and there is a program that computes and prints the factorial of n (=1*2*3*...*n). The text says that there is a logical error in the program but nothing about where it is. And I can't seem to figure out where the logical error is.
Anyone who can help? The program code:
/** Compute the factorial of n */
public class Factorial {
// Print factorial of n
public static void main(String[] args) {
int n = 20;
int factorial = 1;
// n! = 1*2*3...*n
for (int i = 1; i <= n; i++) {
factorial *= i;
}
System.out.println("The Factorial of " + n + " is " + factorial);
}
}
20! is 2,432,902,008,176,640,000 (~ 2*10^18), much larger than the largest possible number that can be stored in an int, which is about 2 billion. This code will overflow and display an incorrect answer.
The correction to be made is to change the declaration of factorial from int to long.
The value of 20! is much bigger than the int type can store.
Use long instead of int
There might not be any Syntax Errors. But there is some error which is unknown to the compiler. Hence it hand overs this problem to OS and the OS immediately terminates the program. This is usually the case with C. Java was made even more powerful by introducing effective EXCEPTION HANDLING to overcome such type of problems i.e., logical errors.
As others have pointed out, the data type is your limitation in this case.
Should you wish to compute large maths, you should use a custom data type specifically suited to represent large numbers.
If you wish to learn about such an implementation, I highly recommend you read PaĆ­lo Ebermann's incredibly thorough answer to this StackOverflow question.
If you have no interest in how the implementation works but simple want to perform a large integer calculation, you can use Java's BigInteger data type.

What data type can be used to hold the value of the factorial of 100,000,000?

Data type to hold a very large number say 1000 or more digits?
I need to find the factorial of a large number say 100000000.
My factorial program works nice for a smaller number.
long factorial(int x)
{
long fact=1;
if(x<0)
{
System.out.println("Incorrect input, enter a positive number");
fact=0;
}
if(x==0)
fact=1;
if(x>0)
{
fact=x;
fact=fact*factorial(x-1);
}
return fact;
}
You need a BigInteger. It can hold an arbitrarily large number.
But in your case 100000000! is such a huge number, that nothing can help.
You should use a log of gamma function, since gamma(n) = (n-1)! Far more efficient than your naive, student way of doing things. It'll be a double in that case, and the natural log will grow more slowly than the value does.
Recursion? Please. Your problem won't be the size of the value you pass back - you'll get too many stack frames and out of memory error long before that.
While BigInteger will theoretically handle such a value, you won't be able to compute it in practise.
First, your algorithm uses recursion, so you'd need 100.000.000 recursive calls of factorial. You'll get stack overflow far before computing the result. You'd have to modify your algorithm to avoid recursion (use a loop for example).
Second, the result will be huge. Using formulas for approximating factorials such as
log n! ~~ n log(n/e)
we can conclude that your number will have more than 750.000.000 digits. While with some luck you might be able to fit it into your memory, you will certainly not be able to compute the number in any reasonable time. Just imagine - you'll have to perform 100.000.000 multiplications with numbers that have hundreds of millions of digits.

Categories

Resources