I want to write a little program which is able to find the first 10 digit long prime number out of the euler number.
The number on the 99th place is the number I am searching for, but the isPrim() method does not respond correctly. Do you see what went wrong?
My Code
public class Main {
public static final String e = "27182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274274663919320030599218174135966";
public static void main(String[] args) {
System.out.println(e);
for (int i = 0; i < e.length() - 10; i++) {
String str = e.substring(i, i + 10);
long num = Long.parseLong(str);
boolean isPrim = isPrim(num);
if (isPrim == true) {
System.out.println("First prime: " + num);
break;
}
System.out.println(i + " " + str + " " + isPrim);
}
}
public static boolean isPrim(long number) {
if (number % 2 == 0) {
return false;
}
for (int j = 3; j * j < number; j+=2) {
if (number % j == 0) {
return false;
}
}
return true;
}
}
Should be j * j <= number, otherwise you will treat squares of primes as primes. I.e. your method says that 9 is prime, because there are no dividers less than sqrt(9).
Also, your code will probably find prime that is shorter than 10 digits, because it checks all 10-digits substrings of E, including those with leading zeros, such as 0452353602.
Also, you need to change type of j to long to avoid overflow.
Related
I have implemented Sieve of Eratosthenes for finding the list of prime number from 1 to n. My code is working fine for inputs from 1 to 10,000 but I am getting following for values >100,000:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -2146737495
at SieveOfEratosthenes.main(SieveOfEratosthenes.java:53)
I am able to find the issue, which is in the for loop when I am doing i * i as it is going out of Integer range (Integer.MAX_VALUE), but I could not find the solution. Can someone suggest me what changes can be done also I appreciate if someone suggest me any improvement for efficiency in this implementation?
public class SieveOfEratosthenes {
public static void main(String[] args) {
Integer num = Integer.parseInt(args[0]);
Node[] nodes = new Node[num + 1];
for(int i = 1; i < nodes.length; i++) {
Node n = new Node();
n.setValue(i);
n.setMarker(true);
nodes[i] = n;
}
for(int i = 1; i < nodes.length; i++) {
if(nodes[i].getMarker() && nodes[i].getValue() > 1) {
System.out.println("Prime " + nodes[i].getValue());
} else {
continue;
}
for(int j = i * i; j < nodes.length
&& nodes[i].getMarker(); j = j + i) {
nodes[j].setMarker(false);
}
}
System.out.println(l.size());
}
}
class Node {
private int value;
private boolean marker;
public void setValue(int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
public void setMarker(boolean marker) {
this.marker = marker;
}
public boolean getMarker() {
return this.marker;
}
public String toString() {
return ("Value : " + marker + " value " + value);
}
}
Essentially, the for(int j = i * i;... loop is to cross out all multiples of i.
It makes sense only to cross out starting from i * i, since all lesser multiples are already crossed out by their lesser divisors.
There are at least two ways to go from here.
First, you can start crossing out from i * 2 instead of i * i.
This will get rid of the overflow.
On the bad side, the complexity of the sieve would grow from O(n log log n) to O(n log n) then.
Second, you can check whether i * i is already too much, and if it is, skip the loop completely.
Recall that it is essentially skipped anyway for i greater than the square root of nodes.length if no overflow occurs.
For example, just add an if (i * 1L * i < nodes.length) before the loop.
for(int i = 1; i < nodes.length; i++) {
if(nodes[i].getMarker() && nodes[i].getValue() > 1) {
System.out.println("Prime " + nodes[i].getValue());
} else {
continue;
}
TO
int limit = 2 << 14;
for(int i = 1; i < nodes.length; i++) {
if(nodes[i].getMarker() && nodes[i].getValue() > 1 && i <= 2 << 15) {
System.out.println("Prime " + nodes[i].getValue());
if (i > limit) {
continue;
}
} else {
continue;
}
I've lurked around for years, but today I have a question concerning my code. I am currently trying to create a collatz program that puts the number of steps for a certain number in an array, but at the same time puts the number of steps for every single number it passes through. Here's my code:
public class GenerousRecursion {
public static short steps;
public static int length;
public static short[] array = new short[101];
public static void main(String[] args) {
length = 100;
for (int count = 2; count < length + 1; count++){
steps = 0;
System.out.println(count + ": " + findCollatz(count));
}
}
public static short findCollatz(int number) {
if (number < length){
if (array[number] > 0) {
steps = array[number]++; return steps;
}
else if(number % 2 == 0) {
array[number] = findCollatz(number / 2);
steps ++;
return steps;
}
else {
array[number] = findCollatz(3 * number + 1);
steps ++;
return steps;
}
}
else {
if(number % 2 == 0) {
findCollatz(number / 2);
steps ++;
return steps;
}
else {
findCollatz(3 * number + 1);
steps ++;
return steps;
}
}
}
}
Here's a great video on the Collatz Conjecture: Numberphile
So here is the error being thrown (reduced), but I don't understand, because I am not anywhere near the bounds of any int or short:
Exception in thread "main" java.lang.StackOverflowError
at GenerousRecursion.findCollatz(GenerousRecursion.java:22)
at GenerousRecursion.findCollatz(GenerousRecursion.java:33)
at GenerousRecursion.findCollatz(GenerousRecursion.java:27)
I just listed these first three lines because these same three lines draw errors for hundreds of lines.
Whats the problem and how do I fix it? Thanks abunch!
Edit: When I ran the debugger, my program continously throws exceptions whenever the array is refrenced.
As stated in the video-clip continuing with 1 will end in an endless loop.
Try the following.
static int[] collatzCounts = new int[100];
static final int NO_COUNT = -1;
static {
Arrays.fill(collatzCounts, NO_COUNT);
collatzCounts{1] = 0; // Define collatz(1) = 0 (1, 4, 2, 1, ...)
}
public static void main(String[] args) {
for (int n = 2; n < 120; n++) {
int steps = countCollatz(n);
System.out.println(n + ": " + steps);
}
}
public static int countCollatz(int n) {
IntFunction f = k ->
k % 2 == 0
? 1 + countCollatz(k / 2)
: 1 + countCollatz(3 * k + 1);
//: 2 + countCollatz((3 * k + 1) / 2);
//if (n == 1) {
// return 0;
//}
if (n < collatzCounts.length) {
if (collatzCounts[n] == NO_COUNT) {
collatzCounts[n] = f.apply(n);
}
return collatzCounts[n];
} else {
return f.apply(n);
}
}
countCollatz simply counts the steps needed - to reach 1 actually. Though till further proof there might be a cycle of higher numbers.
I have used a Java 8 lambda expression, the IntFunction f, as it is more natural to repeat the calculation, once to fill the array, once for too large numberss.
This function its only working for certain numbers, but for 15, or 5 it does not give me correct next prime.
public static int nextPrime(int n) {
boolean isPrime = false;
int m = (int) Math.ceil(Math.sqrt(n));
int start = 3;
if (n % 2 == 0) {
n = n + 1;
}
while (!isPrime) {
isPrime = true;
for (int i = start; i <= m; i = i + 2) {
if (n % i == 0) {
isPrime = false;
break;
}
}
if (!isPrime) {
n = n + 2;
}
}
return n;
}
You don't need to go upto sqrt(n), you need to go upto sqrt(number) that you are evaluating
for example consider you pass n = 5
it will start loop from 3 and it will end the loop at 4 that is not what you need to find next prime number
outer loop
start from n + 1 until you find prime
inner loop
you should start from 3 and sqrt(numberUnderIteration)
You're setting your boundary at the square root of the original number only. In order for you to check if every next number works, you need to recalculate the boundary whenever the n value is changed. So, put int m = (int) Math.ceil(Math.sqrt(n)); inside of your while loop.
You also need to increment n by 1 before you start any calculations, or it will accept n itself as a prime number if it is one. For example, nextPrime(5) would return 5 because it passes the conditions.
And finally, you don't need to increment n by 2 at the end of your while loop because if you are on an even number, it will break out (keep adding 2 to an even number will always be even). I've commented the part of your code that I changed:
public static int nextPrime(int n) {
boolean isPrime = false;
int start = 2; // start at 2 and omit your if statement
while (!isPrime) {
// always incrememnt n at the beginning to check a new number
n += 1;
// redefine max boundary here
int m = (int) Math.ceil(Math.sqrt(n));
isPrime = true;
// increment i by 1, not 2 (you're skipping numbers...)
for (int i = start; i <= m; i++) {
if (n % i == 0) {
isPrime = false;
break;
}
}
// you don't need your "if (!isPrime)..." because you always increment
}
return n;
}
public static void main(String[] args) {
System.out.println(nextPrime(15)); // 17
System.out.println(nextPrime(5)); // 7
System.out.println(nextPrime(8)); // 11
}
You need to compute m inside the for loop.
while (!isPrime) {
isPrime = true;
int m = (int) Math.ceil(Math.sqrt(n));
// do other stuff
Your code works fine except when a prime number is given as input, your method returns input itself.
Example if 5 is your input nextPrime(5) returns 5. If you want 7 (next prime number after 5) to be returned in this case.
Just add n=n+1; at the start of your method. Hope this helps
Just for fun, I coded a quick Prime class that tracks known primes, giving a huge performance boost to finding multiple large primes.
import java.util.ArrayList;
public class Primes {
private static ArrayList<Integer> primes = new ArrayList<Integer>();
public static int nextPrime(int number){
//start it off with the basic primes
if(primes.size() == 0){
primes.add(2);
primes.add(3);
primes.add(5);
primes.add(7);
}
int idx = primes.size()-1;
int last = primes.get(idx);
//check if we already have the prime we are looking for
if(last > number){
//go to the correct prime and return it
boolean high = false;
boolean low = false;
int prevIdx = 0;
int spread = 0;
//keep finagling the index until we're not high or low
while((high = primes.get(idx-1) > number) || (low = primes.get(idx) <= number)){
spread = Math.abs(prevIdx-idx);
//because we always need to move by at least 1 or we will get stuck
spread = spread < 2 ? 2: spread;
prevIdx = idx;
if(high){
idx -= spread/2;
} else if(low){
idx += spread/2;
}
};
return primes.get(idx);
}
/*FIND OUR NEXT SERIES OF PRIMES*/
//just in case 'number' was prime
number++;
int newPrime = last;
//just keep adding primes until we find the right one
while((last = primes.get(primes.size()-1)) < number){
//here we find the next number
newPrime += 2;
//start with the assumption that we have a prime, then try to disprove that
boolean isPrime = true;
idx = 0;
int comparisonPrime;
int sqrt = (int) Math.sqrt(newPrime);
//make sure we haven't gone over the square root limit- also use post-increment so that we use the idx 0
while((comparisonPrime = primes.get(idx++)) <= sqrt){
if(newPrime % comparisonPrime == 0){
isPrime = false;
}
}
if(isPrime){
primes.add(newPrime);
}
}
return last;
}
}
And here is the test:
public class Test {
public static void main(String[] args){
long start;
long end;
int prime;
int number;
number = 1000000;
start = System.currentTimeMillis();
prime = Primes.nextPrime(number);
end = System.currentTimeMillis();
System.out.println("Prime after "+number+" is "+prime+". Took "+(end-start)+" milliseconds.");
number = 500;
start = System.currentTimeMillis();
prime = Primes.nextPrime(number);
end = System.currentTimeMillis();
System.out.println("Prime after "+number+" is "+prime+". Took "+(end-start)+" milliseconds.");
number = 1100000;
start = System.currentTimeMillis();
prime = Primes.nextPrime(number);
end = System.currentTimeMillis();
System.out.println("Prime after "+number+" is "+prime+". Took "+(end-start)+" milliseconds.");
}
}
This results in the following output:
Prime after 1000000 is 1000003. Took 384 milliseconds.
Prime after 500 is 503. Took 10 milliseconds.
Prime after 1100000 is 1100009. Took 65 milliseconds.
As you can see, this takes a long time the first iteration, but we only have to perform that operation once. After that, our time is cut down to almost nothing for primes less than our first number (since it's just a lookup), and it is very fast for primes that are just a bit bigger than our first one (since we have already done most of the work).
EDIT: Updated search for existing primes using a variation on a Binary Search Algorithm. It cut the search time at least in half.
import java.util.Scanner;
class Testing
{
public static void main(String Ar[])
{
int a = 0, i, j;
Scanner in = new Scanner(System.in);
a = in.nextInt();
for (j = a + 1;; j++)
{
for (i = 2; i < j; i++)
{
if (j % i == 0)
break;
}
if (i == j)
{
System.out.println(j);
break;
}
}
}
}
Here is the perfect code for finding next prime for a given number.
public class NextPrime
{
int nextPrime(int x)
{
int num=x,j;
for( j=num+1;;j++)
{
int count=0;
for(int i=1;i<=j;i++)
{
if(j%i==0)
{
count++;
//System.out.println("entered");
}
//System.out.println(count);
}
if(count==2)
{
System.out.println(" next prime is ");
break;
}
}return j;
}
public static void main(String args[])
{
NextPrime np = new NextPrime();
int nxtprm = np.nextPrime(9);
System.out.println(nxtprm);
}
}
//I hope the following code works exactly.
import java.util.Scanner;
public class NextPrime {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Enter a positive integer number : ");
int n = scanner.nextInt();
for (int x = n + 1;; x++) {
boolean isPrime = true;
for (int i = 2; i < x / 2; i++) {
if (x % i == 0) {
isPrime = false;
break;
}
}
if (isPrime) {
System.out.println("Next prime is : " + x);
break;
}
}
}
}
How to find out and print how many numbers you generate before you find the random number?
I have tried many times, and I could not figure out how to print the numbers I generated before I got the prime number. Any guidance or help is greatly appreciated!
public static void main(String[] args) {
int range = 1000000;
Random generator = new Random();
int p = generator.nextInt(range) + 2;
while (!isPrime(p))
p = generator.nextInt(range) + 2;
System.out.println("A random prime number is " + p);
}
private static boolean isPrime(int N) {
for (int i = 2; i <= Math.sqrt(N); i++) {
if (N % i == 0)
return false;
}
return true;
}
This code
while (!isPrime(p))
p = generator.nextInt(range) + 2;
System.out.println("A random prime number is " + p);
}
Will stop when p is actually prime. Otherwise, it'll generate a new random number, add two to it, and claim that the result is prime.
I could not figure out how to print the numbers I generated before I got the prime number* from this line I understand that you want the print generated numbers
You can do this way:
private static boolean isPrime(int N) {
System.out.println(N);
for (int i = 2; i <= Math.sqrt(N); i++) {
if (N % i == 0)
return false;
}
return true;
}
Print statement you have in while prints the random number you generated during the process.In your code you will miss out the first generated number. In order to get all the number's you generated and prime number you can modify the code as below:
private static boolean isPrime(int N) {
for (int i = 2; i <= Math.sqrt(N); i++) {
if (N % i == 0){
System.out.println("A random number is " + N);
return false;
}
}
System.out.println("Prime number is " + N);
return true;
}
public static void main(String[] args) {
int range = 1000000;int count=1;
Random generator = new Random();
int p = generator.nextInt(range) + 2;
while (!isPrime(p)){
count++;
p = generator.nextInt(range) + 2;
//System.out.println("A random prime number is " + p);
}
System.out.println("Total count is"+count);
}
}
I set a count variable in order to verify. count should be equal to the number of times the random number was generated including prime number.
By adding this code to the script:
private static boolean isPrime(int N) {
for (int i = 2; i <= Math.sqrt(N); i++) {
if (N % i == 0)
System.out.println(N+" can be divided by "+i);
return false;
}
return true;
}
You know what number it is can be divided by.
I have got a solution for problem 21 in python and it gives the right answer. I tried out someone else's java code and I get the same answer for a value of 10000 and 100000 but when 1000000 is tried, the solution returned by my code differs from two other solutions returned by java code even though all three solutions returned are same for tested values of 10000 and 1000000 and 50000. Anyone got any ideas?
My Python code
def amicable_pairs(n):
"""returns sum of all amicable pairs under n. See project euler for
definition of an amicable pair"""
div_sum = [0]*n
amicable_pairs_set = [0]*n
for i in range(1, n):
for j in range(i*2, n, i):
div_sum[j] += i
#for i in range(1, n):
# div_sum[i] = sum([j + i/j for j in range(2, int(math.sqrt(i)) + 1) if i % j == 0 and i != i/j])
# div_sum[i] = div_sum[i] + 1
#print div_sum
for j in range(n):
if div_sum[j] < n and div_sum[div_sum[j]] == j and div_sum[j] != j:
amicable_pairs_set[j] = j
amicable_pairs_set[div_sum[j]] = div_sum[j]
return sum(amicable_pairs_set)
Java code 1:
public class AmicableNumbers {
public static void main(String[] args) {
long strTime = System.currentTimeMillis();
int sum_ami = 0;
for (int j = 1; j < 1000000; j++) {
int ad = sum_devisors(j);
if (((sum_devisors(ad)) == j) && (j != ad)) {
sum_ami += j;
}
}
System.out.println(sum_ami);
long endTime = System.currentTimeMillis();
System.out.println("time is " + (endTime - strTime) + " ms");
}
public static int sum_devisors(int number) {
if ((number == 1) || (number == 2)) {
return 1;
}
int sum = 0;
int k = (int) Math.sqrt(number);
for (int i = 2; i < k; i++) {
if (number % i == 0) {
sum += i;
sum += (number / i);
}
}
if (k * k == number) {
sum += k;
}
return (sum + 1);// every number divided by 1
}
}
Java code 2:
import java.util.Scanner;
public class AmicableNumbers {
/**
* #author Pavan Koppolu
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//scan the input
System.out.println("Enter a number, to find out sum of amicable numbers: ");
Scanner scan=new Scanner(System.in);
int input=scan.nextInt();
long before=System.currentTimeMillis();
// getting the result
long result=sumOfAllAmicableNumbersUptoGivenNumber(input);
long after=System.currentTimeMillis();
// prints the result on the console
System.out.println("Sum of all amicable numbers below "+input+" : "+result+" Elasped Time : "+(after-before)+" ms");
}
/*
* calculate the sum of the amicable numbers upto the given number
*/
private static long sumOfAllAmicableNumbersUptoGivenNumber(int input)
{
long sum=0,factorsSum=0,sumOfFactors=0;
for(long j=2;j<input;j++)
{
factorsSum=getFactorsSum(j);
if(j!=factorsSum)
{
sumOfFactors=getFactorsSum(factorsSum);
if(j==sumOfFactors)
sum+=j;
}
else
continue;
}
return sum;
}
/*
* find out the sum of the factors
*/
private static long getFactorsSum(long j)
{
long sum=1;
for(int k=2;k<=Math.sqrt(j);k++)
{
if(j%k==0)
sum+=k+j/k;
}
return sum;
}
}
In fact the solutions returned by all three above differ from each other for an input of 1000000
The point is that there are amicable pairs where one partner is less than 1 million and the other is larger than 1 million, namely
(947835,1125765), (998104,1043096)
The Python code doesn't count them,
for j in range(n):
if div_sum[j] < n and div_sum[div_sum[j]] == j and div_sum[j] != j:
but the Java code counts the smaller members of these pairs. That explains the output of the second Java code, since
25275024 + 947835 + 998104 == 27220963
The output of the first Java code is smaller because it omits the amicable pair
(356408, 399592)
The reason is that
356408 = 596*598
but in the code there is
int k = (int) Math.sqrt(number);
for (int i = 2; i < k; i++) {
thus the divisor sum is miscalculated for all numbers divisible by floor(sqrt(n)) that are not squares (Note that the second Java code miscalculates the divisor sum for all squares).