Ex: n1=100, n2=250, out=233.
Here I have to find the largest odd fibonacci number in the given set of ranges. If an odd fibonacci number doesn't exist then it should return 0. I am getting output as 50 times 0's and then 10 times 233. Where is my mistake and how can I get the desired output?
public class Fibo {
public static void main(String[] args) {
try {
int n1 = 100;
int n2 = 250;
int res = 0;
if (n1 % 2 == 0) {
n1 += 1;
for (int i = n1; i < n2; i += 2) {
if (isPerfectSquare(5 * i * i + 4) || isPerfectSquare(5 * i * i - 4))
res = i;
System.out.println(res);
}
}
} catch(Exception ignored) {
System.out.println("0");
}
}
public static boolean isPerfectSquare(int num) {
double sqrt = Math.sqrt(num);
int x = (int)sqrt;
return Math.pow(sqrt, 2) == Math.pow(x, 2);
}
}
public class Fibonacci {
public static void main(String[] args) {
System.out.println("Enter the starting range");
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
System.out.println("Enter the ending range");
int r = sc.nextInt();
int res = 0;
for (int i = n; i <= r; i++) {
if (isPerfectSquare(5 * i * i + 4) || isPerfectSquare(5 * i * i - 4))
res = i;
}
System.out.println("The biggest odd number in the range is"+" "+res);
}
public static boolean isPerfectSquare(int num) {
double sqrt = Math.sqrt(num);
int x = (int)sqrt;
return Math.pow(sqrt, 2) == Math.pow(x, 2);
}
}
public static int getLargestOddFibonacciBetween(int lo, int hi) {
assert lo <= hi;
int f0 = 0;
int f1 = 1;
int res = -1;
while (f1 <= hi) {
int val = f0 + f1;
f0 = f1;
f1 = val;
if (val >= lo && val <= hi && isOdd(val))
res = val;
}
return res;
}
private static boolean isOdd(int val) {
return (val & 1) == 1;
}
I am currently attempting to solve a ProjectEuler problem and I have got everything down, except the speed. I am almost certain the reason the program executes so slowly is due to the nested loops. I would love some advice on how to speed this up. I am a novice programmer, so I am not familiar with a lot of the more advanced methods/topics.
public class Problem12 {
public static void main(String[] args) {
int num;
for (int i = 1; i < 15000; i++) {
num = i * (i + 1) / 2;
int counter = 0;
for (int x = 1; x <= num; x++) {
if (num % x == 0) {
counter++;
}
}
System.out.println("[" + i + "] - " + num + " is divisible by " + counter + " numbers.");
}
}
}
EDIT : Below is the new code that is exponentially faster. Removed the constant line printing as well to speed it up even more.
public class Problem12 {
public static void main(String[] args) {
int num;
outerloop:
for (int i = 1; i < 25000; i++) {
num = i * (i + 1) / 2;
int counter = 0;
double root = Math.sqrt(num);
for (int x = 1; x < root; x++) {
if (num % x == 0) {
counter += 2;
if (counter >= 500) {
System.out.println("[" + i + "] - " + num + " is divisible by " + counter + " numbers.");
break outerloop;
}
}
}
}
}
}
For starters, when looking at divisors, you never need to go further than the root square of the number, because each divisor below the square root has an equivalent above.
n = a * b => a <= sqrt(n) or b <= sqrt(n)
Then you need to count the other side of the division:
double root = Math.sqrt(num);
for (int x = 1; x < root; x++) {
if (num % x == 0) {
counter += 2;
}
}
The square root is special because it counts only once if it is integer:
if ((double) ((int) root) == root) {
counter += 1;
}
You just need to factorize the number. p^a * q^b * r^c has (a+1)*(b+1)*(c+1) divisors. Here is some basic implementation using this idea:
static int Divisors(int num) {
if (num == 1) {
return 1;
}
int root = (int) Math.sqrt(num);
for (int x = 2; x <= root; x++) {
if (num % x == 0) {
int c = 0;
do {
++c;
num /= x;
} while (num % x == 0);
return (c + 1) * Divisors(num);
}
}
return 2;
}
public static void test500() {
int i = 1, num = 1;
while (Divisors(num) <= 500) {
num += ++i;
}
System.out.println("\nFound: [" + i + "] - " + num);
}
So I am building the petals on a rose game and the dice defined as dice1, dice 2 etc. i then run a loop to decide for each dice what its value is and add that to the game value. What i want is for every sequence of the loop for it to switch which variable it is looking at. So first run through look at dice1. and then second look at dice2.
public class Rosegame
{
private int dice1;
private int dice2;
private int dice3;
private int dice4;
private int dice5;
private int gameValue;
public void rollDice()
{
dice1 = (int) ((6-1+1) * Math.random()) + 1;
dice2 = (int) ((6-1+1) * Math.random()) + 1;
dice3 = (int) ((6-1+1) * Math.random()) + 1;
dice4 = (int) ((6-1+1) * Math.random()) + 1;
dice5 = (int) ((6-1+1) * Math.random()) + 1;
}
public void printValues()
{
System.out.println("Dice 1 is:" + dice1);
System.out.println("Dice 2 is:" + dice2);
System.out.println("Dice 3 is:" + dice3);
System.out.println("Dice 4 is:" + dice4);
System.out.println("Dice 5 is:" + dice5);
}
public int calculatePetalsOnRose()
{
gameValue = 0;
for(int i = 1; i <=5; i++)
{
if (dice1 == 5)
{
gameValue = gameValue + 4;
}
else if (dice1 == 3)
{
gameValue = gameValue + 2;
}
else
{
gameValue = gameValue;
}
}
return gameValue;
}
}
this is my current code and what I need is inside the if statement where it has dice1, i want that to be able to change everytime it loops. Their is also a driver that runs the methods and allows input but so far that is working. Thank you so much in advance
Edit:
switching the variables to an array i now have which gives me an error saying java.lang.NullPointerException. It happens when the rollDice function is being called.
public class PetalsGame
{
private int[] anArrayDice;
private int gameValue;
public void rollDice()
{
anArrayDice[0] = (int) ((6-1+1) * Math.random()) + 1;
anArrayDice[1] = (int) ((6-1+1) * Math.random()) + 1;
anArrayDice[2] = (int) ((6-1+1) * Math.random()) + 1;
anArrayDice[3] = (int) ((6-1+1) * Math.random()) + 1;
anArrayDice[4] = (int) ((6-1+1) * Math.random()) + 1;
}
public void printDice()
{
System.out.println("Dice 1 is:" + anArrayDice[0]);
System.out.println("Dice 2 is:" + anArrayDice[1]);
System.out.println("Dice 3 is:" + anArrayDice[2]);
System.out.println("Dice 4 is:" + anArrayDice[3]);
System.out.println("Dice 5 is:" + anArrayDice[4]);
}
public int calculateAllPetals()
{
gameValue = 0;
for(int i = 0; i <=4; i++)
{
if (anArrayDice[i] == 5)
{
gameValue = gameValue + 4;
}
else if (anArrayDice[i] == 3)
{
gameValue = gameValue + 2;
}
else
{
gameValue = gameValue;
}
}
return gameValue;
}
}
I was able to fix it by adding anArrayDice = new int[5]; inside of the rollDice method. Thank you for the help.
You only seem to roll one die (at least that is the only value you seem to be interested in), so I would start by extracting a method to roll one die. I would also prefer, for readability, Random.nextInt(int). Something like,
private static final Random rand = new Random();
private static int rollDie(int sides) {
return rand.nextInt(sides) + 1;
}
Then you can roll and calculate your rose with that method as needed. Also, you can use x += y; instead of x = x + y;. Something like,
public int calculatePetalsOnRose() {
int gameValue = 0;
for (int i = 1; i <= 5; i++) {
int dice = rollDie(6);
System.out.printf("Dice %d is: %d%n", i, dice);
if (dice == 5) {
gameValue += 4;
} else if (dice == 3) {
gameValue += 2;
}
}
return gameValue;
}
I think it would be alot easier to do this if you use an array to store your dice. Also it saves you from having to repeat the same lines of code over and over again.
public int [] diceArray;
private int gameValue;
public void rollDice()
{
for(int i =0; i < diceArray.length; i++)
{
diceArray[i] = 6 *((int)Math.random()+ 1);
}
}
public void printValues()
{
for(int i=0; i < diceArray.length; i++)
{
System.out.println("Dice" + (i+1) +"is:" + diceArray[i]);
}
}
public int calculatePetalsOnRose()
{
gameValue = 0;
for(int i = 0; i < diceArray.length; i++)
{
if(diceArray[i] == 5)
{
gameValue += 4;
}
else if (diceArray[i] == 3)
{
gameValue +=2;
}
}
return gameValue;
}
I tried to check the validation of credit card using Luhn algorithm, which works as the following steps:
Double every second digit from right to left. If doubling of a digit results in a two-digit number, add up the two digits to get a single-digit number.
2 * 2 = 4
2 * 2 = 4
4 * 2 = 8
1 * 2 = 2
6 * 2 = 12 (1 + 2 = 3)
5 * 2 = 10 (1 + 0 = 1)
8 * 2 = 16 (1 + 6 = 7)
4 * 2 = 8
Now add all single-digit numbers from Step 1.
4 + 4 + 8 + 2 + 3 + 1 + 7 + 8 = 37
Add all digits in the odd places from right to left in the card number.
6 + 6 + 0 + 8 + 0 + 7 + 8 + 3 = 38
Sum the results from Step 2 and Step 3.
37 + 38 = 75
If the result from Step 4 is divisible by 10, the card number is valid; otherwise, it is invalid. For example, the number 4388576018402626 is invalid, but the number 4388576018410707 is valid.
Simply, my program always displays valid for everything that I input. Even if it's a valid number and the result of sumOfOddPlace and sumOfDoubleEvenPlace methods are equal to zero. Any help is appreciated.
import java.util.Scanner;
public class CreditCardValidation {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int count = 0;
long array[] = new long [16];
do
{
count = 0;
array = new long [16];
System.out.print("Enter your Credit Card Number : ");
long number = in.nextLong();
for (int i = 0; number != 0; i++) {
array[i] = number % 10;
number = number / 10;
count++;
}
}
while(count < 13);
if ((array[count - 1] == 4) || (array[count - 1] == 5) || (array[count - 1] == 3 && array[count - 2] == 7)){
if (isValid(array) == true) {
System.out.println("\n The Credit Card Number is Valid. ");
} else {
System.out.println("\n The Credit Card Number is Invalid. ");
}
} else{
System.out.println("\n The Credit Card Number is Invalid. ");
}
}
public static boolean isValid(long[] array) {
int total = sumOfDoubleEvenPlace(array) + sumOfOddPlace(array);
if ((total % 10 == 0)) {
for (int i=0; i< array.length; i++){
System.out.println(array[i]);}
return true;
} else {
for (int i=0; i< array.length; i++){
System.out.println(array[i]);}
return false;
}
}
public static int getDigit(int number) {
if (number <= 9) {
return number;
} else {
int firstDigit = number % 10;
int secondDigit = (int) (number / 10);
return firstDigit + secondDigit;
}
}
public static int sumOfOddPlace(long[] array) {
int result = 0;
for (int i=0; i< array.length; i++)
{
while (array[i] > 0) {
result += (int) (array[i] % 10);
array[i] = array[i] / 100;
}}
System.out.println("\n The sum of odd place is " + result);
return result;
}
public static int sumOfDoubleEvenPlace(long[] array) {
int result = 0;
long temp = 0;
for (int i=0; i< array.length; i++){
while (array[i] > 0) {
temp = array[i] % 100;
result += getDigit((int) (temp / 10) * 2);
array[i] = array[i] / 100;
}
}
System.out.println("\n The sum of double even place is " + result);
return result;
}
}
You can freely import the following code:
public class Luhn
{
public static boolean Check(String ccNumber)
{
int sum = 0;
boolean alternate = false;
for (int i = ccNumber.length() - 1; i >= 0; i--)
{
int n = Integer.parseInt(ccNumber.substring(i, i + 1));
if (alternate)
{
n *= 2;
if (n > 9)
{
n = (n % 10) + 1;
}
}
sum += n;
alternate = !alternate;
}
return (sum % 10 == 0);
}
}
Link reference: https://github.com/jduke32/gnuc-credit-card-checker/blob/master/CCCheckerPro/src/com/gnuc/java/ccc/Luhn.java
Google and Wikipedia are your friends. Instead of long-array I would use int-array. On Wikipedia following java code is published (together with detailed explanation of Luhn algorithm):
public static boolean check(int[] digits) {
int sum = 0;
int length = digits.length;
for (int i = 0; i < length; i++) {
// get digits in reverse order
int digit = digits[length - i - 1];
// every 2nd number multiply with 2
if (i % 2 == 1) {
digit *= 2;
}
sum += digit > 9 ? digit - 9 : digit;
}
return sum % 10 == 0;
}
You should work on your input processing code. I suggest you to study following solution:
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
boolean repeat;
List<Integer> digits = new ArrayList<Integer>();
do {
repeat = false;
System.out.print("Enter your Credit Card Number : ");
String input = in.next();
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (c < '0' || c > '9') {
repeat = true;
digits.clear();
break;
} else {
digits.add(Integer.valueOf(c - '0'));
}
}
} while (repeat);
int[] array = new int[digits.size()];
for (int i = 0; i < array.length; i++) {
array[i] = Integer.valueOf(digits.get(i));
}
boolean valid = check(array);
System.out.println("Valid: " + valid);
}
I took a stab at this with Java 8:
public static boolean luhn(String cc) {
final boolean[] dbl = {false};
return cc
.chars()
.map(c -> Character.digit((char) c, 10))
.map(i -> ((dbl[0] = !dbl[0])) ? (((i*2)>9) ? (i*2)-9 : i*2) : i)
.sum() % 10 == 0;
}
Add the line
.replaceAll("\\s+", "")
Before
.chars()
If you want to handle whitespace.
Seems to produce identical results to
return LuhnCheckDigit.LUHN_CHECK_DIGIT.isValid(cc);
From Apache's commons-validator.
There are two ways to split up your int into List<Integer>
Use %10 as you are using and store it into a List
Convert to a String and then take the numeric values
Here are a couple of quick examples
public static void main(String[] args) throws Exception {
final int num = 12345;
final List<Integer> nums1 = splitInt(num);
final List<Integer> nums2 = splitString(num);
System.out.println(nums1);
System.out.println(nums2);
}
private static List<Integer> splitInt(int num) {
final List<Integer> ints = new ArrayList<>();
while (num > 0) {
ints.add(0, num % 10);
num /= 10;
}
return ints;
}
private static List<Integer> splitString(int num) {
final List<Integer> ints = new ArrayList<>();
for (final char c : Integer.toString(num).toCharArray()) {
ints.add(Character.getNumericValue(c));
}
return ints;
}
I'll use 5 digit card numbers for simplicity. Let's say your card number is 12345; if I read the code correctly, you store in array the individual digits:
array[] = {1, 2, 3, 4, 5}
Since you already have the digits, in sumOfOddPlace you should do something like
public static int sumOfOddPlace(long[] array) {
int result = 0;
for (int i = 1; i < array.length; i += 2) {
result += array[i];
}
return result;
}
And in sumOfDoubleEvenPlace:
public static int sumOfDoubleEvenPlace(long[] array) {
int result = 0;
for (int i = 0; i < array.length; i += 2) {
result += getDigit(2 * array[i]);
}
return result;
}
this is the luhn algorithm implementation which I use for only 16 digit Credit Card Number
if(ccnum.length()==16){
char[] c = ccnum.toCharArray();
int[] cint = new int[16];
for(int i=0;i<16;i++){
if(i%2==1){
cint[i] = Integer.parseInt(String.valueOf(c[i]))*2;
if(cint[i] >9)
cint[i]=1+cint[i]%10;
}
else
cint[i] = Integer.parseInt(String.valueOf(c[i]));
}
int sum=0;
for(int i=0;i<16;i++){
sum+=cint[i];
}
if(sum%10==0)
result.setText("Card is Valid");
else
result.setText("Card is Invalid");
}else
result.setText("Card is Invalid");
If you want to make it use on any number replace all 16 with your input number length.
It will work for Visa number given in the question.(I tested it)
Here's my implementation of the Luhn Formula.
/**
* Runs the Luhn Equation on a user inputed CCN, which in turn
* determines if it is a valid card number.
* #param c A user inputed CCN.
* #param cn The check number for the card.
* #return If the card is valid based on the Luhn Equation.
*/
public boolean luhn (String c, char cn)
{
String card = c;
String checkString = "" + cn;
int check = Integer.valueOf(checkString);
//Drop the last digit.
card = card.substring(0, ( card.length() - 1 ) );
//Reverse the digits.
String cardrev = new StringBuilder(card).reverse().toString();
//Store it in an int array.
char[] cardArray = cardrev.toCharArray();
int[] cardWorking = new int[cardArray.length];
int addedNumbers = 0;
for (int i = 0; i < cardArray.length; i++)
{
cardWorking[i] = Character.getNumericValue( cardArray[i] );
}
//Double odd positioned digits (which are really even in our case, since index starts at 0).
for (int j = 0; j < cardWorking.length; j++)
{
if ( (j % 2) == 0)
{
cardWorking[j] = cardWorking[j] * 2;
}
}
//Subtract 9 from digits larger than 9.
for (int k = 0; k < cardWorking.length; k++)
{
if (cardWorking[k] > 9)
{
cardWorking[k] = cardWorking[k] - 9;
}
}
//Add all the numbers together.
for (int l = 0; l < cardWorking.length; l++)
{
addedNumbers += cardWorking[l];
}
//Finally, check if the number we got from adding all the other numbers
//when divided by ten has a remainder equal to the check number.
if (addedNumbers % 10 == check)
{
return true;
}
else
{
return false;
}
}
I pass in the card as c which I get from a Scanner and store in card, and for cn I pass in checkNumber = card.charAt( (card.length() - 1) );.
Okay, this can be solved with a type conversions to string and some Java 8
stuff. Don't forget numbers and the characters representing numbers are not the same. '1' != 1
public static int[] longToIntArray(long cardNumber){
return Long.toString(cardNumber).chars()
.map(x -> x - '0') //converts char to int
.toArray(); //converts to int array
}
You can now use this method to perform the luhn algorithm:
public static int luhnCardValidator(int cardNumbers[]) {
int sum = 0, nxtDigit;
for (int i = 0; i<cardNumbers.length; i++) {
if (i % 2 == 0)
nxtDigit = (nxtDigit > 4) ? (nxtDigit * 2 - 10) + 1 : nxtDigit * 2;
sum += nxtDigit;
}
return (sum % 10);
}
private static int luhnAlgorithm(String number){
int n=0;
for(int i = 0; i<number.length(); i++){
int x = Integer.parseInt(""+number.charAt(i));
n += (x*Math.pow(2, i%2))%10;
if (x>=5 && i%2==1) n++;
}
return n%10;
}
public class Creditcard {
public static void main(String args[]){
Scanner sc=new Scanner(System.in);
String cardno = sc.nextLine();
if(checkType(cardno).equals("U")) //checking for unknown type
System.out.println("UNKNOWN");
else
checkValid(cardno); //validation
}
private static String checkType(String S)
{
int AM=Integer.parseInt(S.substring(0,2));
int D=Integer.parseInt(S.substring(0,4)),d=0;
for(int i=S.length()-1;i>=0;i--)
{
if(S.charAt(i)==' ')
continue;
else
d++;
}
if((AM==34 || AM==37) && d==15)
System.out.println("AMEX");
else if(D==6011 && d==16)
System.out.println("Discover");
else if(AM>=51 && AM<=55 && d==16)
System.out.println("MasterCard");
else if(((S.charAt(0)-'0')==4)&&(d==13 || d==16))
System.out.println("Visa");
else
return "U";
return "";
}
private static void checkValid(String S) // S--> cardno
{
int i,d=0,sum=0,card[]=new int[S.length()];
for(i=S.length()-1;i>=0;i--)
{
if(S.charAt(i)==' ')
continue;
else
card[d++]=S.charAt(i)-'0';
}
for(i=0;i<d;i++)
{
if(i%2!=0)
{
card[i]=card[i]*2;
if(card[i]>9)
sum+=digSum(card[i]);
else
sum+=card[i];
}
else
sum+=card[i];
}
if(sum%10==0)
System.out.println("Valid");
else
System.out.println("Invalid");
}
public static int digSum(int n)
{
int sum=0;
while(n>0)
{
sum+=n%10;
n/=10;
}
return sum;
}
}
Here is the implementation of Luhn algorithm.
public class LuhnAlgorithm {
/**
* Returns true if given card number is valid
*
* #param cardNum Card number
* #return true if card number is valid else false
*/
private static boolean checkLuhn(String cardNum) {
int cardlength = cardNum.length();
int evenSum = 0, oddSum = 0, sum;
for (int i = cardlength - 1; i >= 0; i--) {
System.out.println(cardNum.charAt(i));
int digit = Character.getNumericValue(cardNum.charAt(i));
if (i % 2 == 0) {
int multiplyByTwo = digit * 2;
if (multiplyByTwo > 9) {
/* Add two digits to handle cases that make two digits after doubling */
String mul = String.valueOf(multiplyByTwo);
multiplyByTwo = Character.getNumericValue(mul.charAt(0)) + Character.getNumericValue(mul.charAt(1));
}
evenSum += multiplyByTwo;
} else {
oddSum += digit;
}
}
sum = evenSum + oddSum;
if (sum % 10 == 0) {
System.out.println("valid card");
return true;
} else {
System.out.println("invalid card");
return false;
}
}
public static void main(String[] args) {
String cardNum = "4071690065031703";
System.out.println(checkLuhn(cardNum));
}
}
public class LuhnAlgorithm {
/**
* Returns true if given card number is valid
*
* #param cardNum Card number
* #return true if card number is valid else false
*/
private static boolean checkLuhn(String cardNum) {
int cardlength = cardNum.length();
int evenSum = 0, oddSum = 0, sum;
for (int i = cardlength - 1; i >= 0; i--) {
System.out.println(cardNum.charAt(i));
int digit = Character.getNumericValue(cardNum.charAt(i));
if (i % 2 == 0) {
int multiplyByTwo = digit * 2;
if (multiplyByTwo > 9) {
/* Add two digits to handle cases that make two digits after doubling */
String mul = String.valueOf(multiplyByTwo);
multiplyByTwo = Character.getNumericValue(mul.charAt(0)) + Character.getNumericValue(mul.charAt(1));
}
evenSum += multiplyByTwo;
} else {
oddSum += digit;
}
}
sum = evenSum + oddSum;
if (sum % 10 == 0) {
System.out.println("valid card");
return true;
} else {
System.out.println("invalid card");
return false;
}
}
public static void main(String[] args) {
String cardNum = "8112189875";
System.out.println(checkLuhn(cardNum));
}
}
Hope it may works.
const options = {
method: 'GET',
headers: {Accept: 'application/json', 'X-Api-Key': '[APIkey]'}
};
fetch('https://api.epaytools.com/Tools/luhn?number=[CardNumber]&metaData=true', options)
.then(response => response.json())
.then(response => console.log(response))
.catch(err => console.error(err));
I am printing out a list of prime numbers in a program and storing it an array. Then I want to get the the prime number on a particular index instead of the total list..
import java.util.*;
public class Gauss {
static int n;
static int[] array;
public static void Input() {
Scanner input = new Scanner(System.in);
System.out.println("Enter N: ");
n = input.nextInt();
}
public static boolean isPrime(int num) {
boolean prime = true;
int limit = (int) Math.sqrt(num);
for (int i = 2; i <= limit; i++) {
if (num % i == 0) {
prime = false;
break;
}
}
return prime;
}
public static void Calc() {
Input();
array = new int[1000];
for (int i = 2; i < array.length; i++) {
array[i] = i;
}
ArrayList<Integer> list = new ArrayList<Integer>(array.length);
for (int c : array) {
list.add(c);
}
list.remove(0);
list.remove(0);
Collections.sort(list);
for (int k : list) {
if (isPrime(k)) {
System.out.println(k);
}
}
}
public static void main(String[] args) {
Calc();
}
}
To get the nth prime just use array[n-1]
You might find this answer useful to a similar question.
And you can get the nth prime numbers with
List<Integer> primes = findPrimes(0, n);
System.out.println( primes.get(i) );
** EDIT **
Here is the integral test program that I came up (modified since the last posted answer above) with benchmark tests and all. I know there are faster implementations, and some optimizations can still be made, but here are some algorithms to generate prime numbers :
public class PrimeTests {
public static void main(String... args) {
AbstractPrimeGenerator[] generators = new AbstractPrimeGenerator[] {
new DefaultPrimeGenerator(),
new AtkinSievePrimeGenerator(),
new SundaramSievePrimeGenerator()
};
int[] primes;
int[] old_primes = null;
double[] testAvg = new double[generators.length];
long ts, te;
double time;
DecimalFormat df = new DecimalFormat("0.0######################");
int max = 10000000;
int testCountLoop = 10;
int it = 0, ti;
while (it++ < testCountLoop) {
ti = 0;
for (AbstractPrimeGenerator g : generators) {
ti++;
System.out.println(it + "." + ti + ". Calculating " + max
+ " primes numbers from " + g.getName() + "...");
ts = System.nanoTime();
primes = g.findPrimes(max);
te = System.nanoTime();
time = (te - ts) * Math.pow(10, -9) * 1000;
df.setRoundingMode(RoundingMode.HALF_UP);
testAvg[ti - 1] += time;
System.out.println("Found " + primes.length
+ " prime numbers (in " + time + " ms, "
+ df.format(time / primes.length) + " ms per prime)");
// for (int prime : primes) {
// System.out.print(prime + "... ");
// }
// System.out.println();
if (old_primes != null) {
System.out.print("Validating primes.... ");
if (primes.length == old_primes.length) {
for (int i = 0; i < primes.length; i++) {
if (primes[i] != old_primes[i]) {
System.out.println("Prime number does not match : " + primes[i] + " != " + old_primes[i] + " at index " + i);
System.exit(-1);
}
}
} else {
System.out.println("ERROR!! No match in prime results");
System.exit(-1);
}
System.out.println("Ok!");
}
old_primes = primes;
}
System.out.println("................");
}
System.out.println("Results:");
ti = 0;
for (AbstractPrimeGenerator g : generators) {
time = (testAvg[ti++] / testCountLoop);
System.out.println(ti + ". Average time finding " + max
+ " primes numbers from " + g.getName() + " = " + time
+ " ms or " + df.format(time / old_primes.length)
+ " ms per prime");
}
System.out.println("Done!");
}
/**
* Base class for a prime number generator
*/
static abstract public class AbstractPrimeGenerator {
/**
* The name of the generator
*
* #return String
*/
abstract public String getName();
/**
* Returns all the prime numbers where (2 <= p <= max)
*
* #param max
* int the maximum value to test for a prime
* #return int[] an array of prime numbers
*/
abstract public int[] findPrimes(int max);
}
/**
* Default naive prime number generator. Based on the assumption that any
* prime n is not divisible by any other prime m < n (or more precisely m <=
* sqrt(n))
*/
static public class DefaultPrimeGenerator extends AbstractPrimeGenerator {
#Override
public String getName() {
return "Default generator";
}
#Override
public int[] findPrimes(int max) {
int[] primes = new int[max];
int found = 0;
boolean isPrime;
// initial prime
if (max > 2) {
primes[found++] = 2;
for (int x = 3; x <= max; x += 2) {
isPrime = true; // prove it's not prime
for (int i = 0; i < found; i++) {
isPrime = x % primes[i] != 0; // x is not prime if it is
// divisible by p[i]
if (!isPrime || primes[i] * primes[i] > x) {
break;
}
}
if (isPrime) {
primes[found++] = x; // add x to our prime numbers
}
}
}
return Arrays.copyOf(primes, found);
}
}
/**
* Sieve of Atkin prime number generator Implementation following the Sieve
* of Atkin to generate prime numbers
*
* #see http://en.wikipedia.org/wiki/Sieve_of_Atkin
*/
static public class AtkinSievePrimeGenerator extends AbstractPrimeGenerator {
#Override
public String getName() {
return "Sieve of Atkin generator";
}
#Override
public int[] findPrimes(int max) {
boolean[] isPrime = new boolean[max + 1];
double sqrt = Math.sqrt(max);
for (int x = 1; x <= sqrt; x++) {
for (int y = 1; y <= sqrt; y++) {
int n = 4 * x * x + y * y;
if (n <= max && (n % 12 == 1 || n % 12 == 5)) {
isPrime[n] = !isPrime[n];
}
n = 3 * x * x + y * y;
if (n <= max && (n % 12 == 7)) {
isPrime[n] = !isPrime[n];
}
n = 3 * x * x - y * y;
if (x > y && (n <= max) && (n % 12 == 11)) {
isPrime[n] = !isPrime[n];
}
}
}
for (int n = 5; n <= sqrt; n++) {
if (isPrime[n]) {
int s = n * n;
for (int k = s; k <= max; k += s) {
isPrime[k] = false;
}
}
}
int[] primes = new int[max];
int found = 0;
if (max > 2) {
primes[found++] = 2;
}
if (max > 3) {
primes[found++] = 3;
}
for (int n = 5; n <= max; n += 2) {
if (isPrime[n]) {
primes[found++] = n;
}
}
return Arrays.copyOf(primes, found);
}
}
/**
* Sieve of Sundaram prime number generator Implementation following the
* Sieve of Sundaram to generate prime numbers
*
* #see http://en.wikipedia.org/wiki/Sieve_of_Sundaram
*/
static public class SundaramSievePrimeGenerator extends
AbstractPrimeGenerator {
#Override
public String getName() {
return "Sieve of Sundaram generator";
}
#Override
public int[] findPrimes(int max) {
int n = max / 2;
boolean[] isPrime = new boolean[max];
Arrays.fill(isPrime, true);
for (int i = 1; i < n; i++) {
for (int j = i; j <= (n - i) / (2 * i + 1); j++) {
isPrime[i + j + 2 * i * j] = false;
}
}
int[] primes = new int[max];
int found = 0;
if (max > 2) {
primes[found++] = 2;
}
for (int i = 1; i < n; i++) {
if (isPrime[i]) {
primes[found++] = i * 2 + 1;
}
}
return Arrays.copyOf(primes, found);
}
}
}
On my machine, the result gives :
Results:
1. Average time finding 10000000 primes numbers from Default generator = 1108.7848961000002 ms or 0.0016684019448402676 ms per prime
2. Average time finding 10000000 primes numbers from Sieve of Atkin generator = 199.8792727 ms or 0.0003007607413114167 ms per prime
3. Average time finding 10000000 primes numbers from Sieve of Sundaram generator = 132.6467922 ms or 0.00019959522073372766 ms per prime
Using one of the class's method above (you don't need the actual base class and all, only the actual method), you can do :
public class PrimeTest2 {
static public int[] findPrimes(int max) {
int[] primes = new int[max];
int found = 0;
boolean isPrime;
// initial prime
if (max > 2) {
primes[found++] = 2;
for (int x = 3; x <= max; x += 2) {
isPrime = true; // prove it's not prime
for (int i = 0; i < found; i++) {
isPrime = x % primes[i] != 0; // x is not prime if it is
// divisible by p[i]
if (!isPrime || primes[i] * primes[i] > x) {
break;
}
}
if (isPrime) {
primes[found++] = x; // add x to our prime numbers
}
}
}
return Arrays.copyOf(primes, found);
}
public static void main(String... args) {
Scanner input = new Scanner(System.in);
int MAX_N = Integer.MAX_VALUE / 100;
int n = 0;
while (n <= 0 || n >= MAX_N) {
System.out.print("Enter N: ");
n = input.nextInt();
if (n <= 0) {
System.out.println("n must be greater than 0");
}
if (n >= MAX_N) {
System.out.println("n must be smaller than " + MAX_N);
}
}
int max = n * 100; // just find enough prime numbers....
int[] primes = findPrimes(max);
System.out.println("Number of prime numbers found from " + 0 + " to "
+ max + " = " + primes.length);
System.out.println("The " + n
+ (n == 1 ? "st" : n == 2 ? "nd" : n == 3 ? "rd" : "th")
+ " prime number is : " + primes[n - 1]);
}
}
Which will output (for example) :
Enter N: 10000
Number of prime numbers found from 0 to 1000000 = 78498
The 10000th prime number is : 104729
With that in hand, you pretty have all that is to say about finding the nth prime number. For larger numbers (beyond int's), you'll have to modify the "default generator's" un-optimized method to accept long or use other methodologies (i.e. other language and/or libraries)
Cheers!
The code you have is pretty much the way to go, and Roflcopter's answer for picking the number is correct, but there is one optimization you could do that would significantly increase the performance. Instead of dividing by all numbers less than or equal to the square root, divide only by PRIMES less than or equal to the square root. Any number not divisible by any prime you've found so far is also not divisible by any combination of same, which is the definition of a nonprime number (having a prime factorization other than 1*N)