I need to print all prime numbers from 1 to 1,000,000 and print all even numbers from 4 to 10,000 and two prime numbers that sum to it.
I have a sieve method that changes all non-prime numbers in an array to a 0 (the problem specifically asks for this to be done), and I need to use a goldbach method that passes this array and displays all even numbers from 4 to 10,000 and two primes that sum up to that number.
The point of the goldbach portion of the problem is to print the numbers efficiently, and I am pretty sure my solution uses a polynomial time search when the correct solution is to be done with a linear time search. Any clue on how I might optimize this?
import java.lang.Math;
public class sieveAndGoldbach {
public static void sieve(int[] a) {
int n = a.length;
a[0] = 0;
for (int i = 1; i <= Math.sqrt(n); i++) {
if (a[i] != 0) {
for (int j = a[i]*a[i]; j <= n; j+=a[i]) {
a[j-1] = 0;
}
}
}
}
public static void goldbach(int[] a) {
int max = 10000;
for (int i = 4; i <= max; i += 2) {
int count = 0;
for (int j = 0; j < i/2; j++) {
if (a[j] != 0) {
int difference = i-a[j];
for (int k = 0; k < max; k++) {
if (a[k] == difference && count == 0) {
System.out.println(i + " = " + a[j] + " + " + (difference));
count++;
}
}
}
}
}
}
public static void main(String[] args) {
//initialize and fill array from 1 to n
int n = 1000000; //initially one million GOLDBACH METHOD WILL NOT WORK FOR n < 10,000
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = i + 1;
}
//Call sieve method on array a, then print all primes, not the zeros
sieve(a);
for (int i = 0; i < n; i++) {
if (a[i] != 0) {
System.out.print(a[i]);
System.out.print(" ");
}
}
System.out.print("\n");
//Call goldbach method on array a
goldbach(a);
}
}
You currently seem to be iterating through the array of primes for each prime looking for one that sums to your target. That's not necessary; you just need to check whether the difference is a prime:
int[] primes;
int target;
for (int i = 2; i < target / 2; i++) {
if (primes[i] != 0 && primes[target - i] != 0)
...
}
Beyond that I can't see a lot of obvious optimisation but there may well be some numerical analysis that allows you to target likely primes first.
Related
I already generated primes using the Sieve of Eratosthenes algorithm (I asked about it here Sieve of Eratosthenes, generating primes. Problem with loops)
But now I have to do it using only an array and nested loops.
I tried to apply this approch https://examples.javacodegeeks.com/java-basics/for-loop/generate-prime-numbers-with-for-loop/, but I can't get why it doesn't work correctly for me
I just want to check if a number is prime and add it to my array
Could u help me pls?
public class Part6 {
public static int[] primeSequence(int n) {
int[] primes = new int[n];
for (int i = 2; i < n; i++) {
boolean isPrimeNumber = true;
for (int j = i + 1; j < i; j++) {
if(j % i == 0)
isPrimeNumber = false;
break;
}
if (isPrimeNumber)
primes[i] = i;
}
return primes;
}
public static void main(String[] args) {
for (int number : primeSequence(Integer.parseInt(args[0]))) {
System.out.print(number);
}
}
}
You are missing braces in your inner loop, your inner loop doesn't get executed (int j = i + 1; j < i!), the order of operands in the modulo operation is wrong and the inner loop should probably start at 2.
for (int j = 2; j < i; j++) {
if(i % j) == 0){
isPrimeNumber = false;
break;
}
}
If we start the second loop from j=i+1 then we will miss many numbers which might be a divisor of the number i. So, to check if i is a prime or not we should start with j=2 for every i-th iteration.
Also, inside every nested loop we are checking if i is Prime or not so, we should whether i % j == 0 or not.
Here is a modified version:
public static int[] primeSequence(int n)
{
int k = 0;
int[] primes = new int[n];
for (int i = 1; i < n; i++)
{
boolean isPrimeNumber = true;
for (int j = 2; j < i; j++)
{
if (i % j == 0)
{
isPrimeNumber = false;
break;
}
}
if (isPrimeNumber)
primes[k++] = i;
}
return primes;
}
public class PrimeNumbers {
public static void main(String[] args) {
int i = 1000000000;
int m=2;
int n=1;
for (int j = 2; j < i; j++) {
int l=0;
if(j%25==0)
{
if(j%100==0)
{
m++;
}
if(j%1000==0)
{
m++;
}
m++;
}
if (j % 2 != 0) {
for (int k = 2; k < j/m; k++) {
if (j % k == 0) {
l++;
}
}
if (l < 1) {
n++;
}
if(n==1001)
{
System.out.print(j);
}
}
}
}
}
It works fine for numbers till ~100 million but as I'm going for larger numbers the result is inconsistent. I've seen the algorithms for prime numbers, just thought of trying.
int's are limited to represent numbers to approx. 2.1 billion. Past that the integer will begin to wrap around. Use the long data type instead and you will be able to go much higher.
I dont know what you are trying to do exactly, but what i judge you want to identify the prime numbers until the number you have specified... if this is what you need, here is the code:
public class PrimeNumbers {
public static void main(String[] args) {
int number = 20000;
int i = 1;
int j = 0;
while (i <= number) {
j = 1;
int counter = 0;
while (j <= i){
int divide = i / j;
if (i % j == 0){
counter++;
}
j++;
}
if (counter <= 2) {
System.out.print(i + " ");
}
i++;
}
}
}
I am writing a program to tell me all the perfect numbers between 1 and 500 and I made this program, but it doesn't work although the algorithm makes sense.
import java.util.Scanner;
class allPerfect {
public static void main(String args[]) {
int sum = 0;
System.out.println("All perfect numbers between 1 and 500 are:");
for (int j = 0; j != 501; j++) {
for (int i = 1; i < j; i++) {
if (j % i == 0) {
sum = sum + i;
if (sum == j) {
System.out.println(j);
sum = 0;
} else {
sum = 0;
}
}
}
}
}
}
What's wrong here?
Please find the comment in-line.
class allPerfect {
public static void main(String args[]){
int sum;
System.out.println("All perfect numbers between 1 and 500 are:");
for(int j = 1; j!=501; j++){
sum = 0; //**You should reset the sum at the start of the inner loop.**
for(int i = 1; i < j; i++ ){
if(j % i == 0) {
sum = sum + i;
}
}
if(sum == j) { //------ statement-1
System.out.println(j);
}
}
}
}
statement-1 you check the sum of all the divisor is equal to the number, after summing up for all the numbers less than j.
You can ignore all the odd number (j) in outer loop, because odd perfect number does not exist. To be precise: it is not known that odd perfect number exists.
You are resetting sum before you finish finding all of a numbers divisors.
for(int i = 1; i < j; i++ ){
if(j % i == 0){
sum = sum + i;
if(sum == j){
System.out.println(j);
sum = 0;
}else{
sum = 0;
}
}
}
You should do the if(sum == j) only after you exit the inner for loop.
When I run this code to find sum of prime numbers below 20 it works fine, but when try to find sum below 2500000 it takes too much time. It's been at least 20 minutes and it's still running. It seems like it's not working. How do I fix it?
class PrimeSummation {
public static void main(String[] args) {
int sum = 0;
for(int i = 1; i < 2500000; i++) {
int count = 0;
for(int j = 1; j < i + 1; j++) {
if((i%j) == 0) {
count++;
}
}
if(count == 2) {
sum += i;
}
}
System.out.println(sum);
}
}
sum cannot be an int because the answer is 219697708195 whereas Integer.MAX_VALUE is only 2147483647. You must use a long or a BigInteger instead.
Your algorithm is very slow, because for every one of the 2500000 numbers you are starting from scratch to decide whether it is prime or not, and your approach for testing whether a number is prime (try every possible factor) is not very efficient.
The following code produces the answer in about a tenth of a second on my machine.
int num = 2500000;
long sum = 0;
boolean[] arr = new boolean[num];
for (int p = 2; p < num; p++) {
if (!arr[p]) {
sum += p;
for (int k = p * 2; k < num; k += p)
arr[k] = true;
}
}
System.out.println(sum);
Keeping track of previously found primes seems to help:
BigInteger sum = BigInteger.ZERO;
List<Integer> primes = new ArrayList<>();
for(int i = 2; i < 2500000; i++) {
boolean isPrime = true;
for(int j = 0; j < primes.size() && primes.get(j)<= Math.sqrt(i); j++) {
int p = primes.get(j);
if((i%p) == 0) {
isPrime=false;
break;
}
}
if(isPrime) {
sum = sum.add(BigInteger.valueOf(i));
primes.add(i);
}
}
System.out.println(sum);
Came up with answer:
219697708195
If you want better performance for generating a large number prime number, you should use Sieve formula.
You can Learn Sieve_of_Eratosthenes formula for prime number generation.
According to Sieve_of_Eratosthenes:
import java.util.*;
public class Sieve
{
private BitSet sieve;
private Sieve() {}
private Sieve(int size) {
sieve = new BitSet((size+1)/2);
}
private boolean is_composite(int k)
{
assert k >= 3 && (k % 2) == 1;
return sieve.get((k-3)/2);
}
private void set_composite(int k)
{
assert k >= 3 && (k % 2) == 1;
sieve.set((k-3)/2);
}
public static List<Integer> sieve_of_eratosthenes(int max)
{
Sieve sieve = new Sieve(max + 1); // +1 to include max itself
for (int i = 3; i*i <= max; i += 2) {
if (sieve.is_composite(i))
continue;
// We increment by 2*i to skip even multiples of i
for (int multiple_i = i*i; multiple_i <= max; multiple_i += 2*i)
sieve.set_composite(multiple_i);
}
List<Integer> primes = new ArrayList<Integer>();
primes.add(2);
for (int i = 3; i <= max; i += 2)
if (!sieve.is_composite(i))
primes.add(i);
return primes;
}
}
Performance:
Consider the following Java program:
public class RelativelyPrime {
public static void main(String[] args) {
int N = Integer.parseInt(args[0]); // Dimensions of grid
int i, j;
int r; // Remainder when i is divided by j
for (i = 1; i <= N; i++) {
for (j = 1; j <= N; j++) {
do { // Using Euclidean algorithm
r = i % j;
i = j;
j = r;
} while (r > 0);
if (i == 1) System.out.print("*");
else System.out.print(" ");
}
System.out.println();
}
}
}
This program prints an N x N table (or matrix, if you like) where N is a command-line argument.
The (i, j)-entry is a * if i and j are relatively prime, or a single whitespace if they are not relatively prime. When I run the program by entering, for instance, java RelativelyPrime 3 it endlessly prints *. Why is this happening?
You changed i and j in the while loop.
for (i = 1; i <= N; i++) {
for (j = 1; j <= N; j++) {
int ii = i, jj = j;
do { // Using Euclidean algorithm
r = ii % jj;
ii = jj;
jj = r;
} while (r > 0);
if (ii == 1) System.out.print("*");
else System.out.print(" ");
}
System.out.println();
}
This is where using the debugger would have helped you solve the problem.
Inside your loops, you alter both i and j which means they never reach N and thus you have an infinite loop.
I suggest you not alter these variables but instead use two new variables, ideally with meaningful names.