Calculate nth prime.. in java? - java

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)

Related

Finding the smith number between given range

I will get to the point quickly. Basically smith numbers are: Composite number the sum of whose digits is the sum of the digits of its prime factors (excluding 1). (The primes are excluded since they trivially satisfy this condition). One example of a Smith number is the beast number 666=2·3·3·37, since 6+6+6=2+3+3+(3+7)=18.
what i've tried:
In a for loop first i get the sum of the current number's(i) digits
In same loop i try to get the sum of the number's prime factors digits.
I've made another method to check if current number that is going to proccessed in for loop is prime or not,if its prime it will be excluded
But my code is seems to not working can you guys help out?
public static void main(String[] args) {
smithInrange(1, 50);
}
public static void smithInrange(int start_val, int end_val) {
for (int i = start_val; i < end_val; i++) {
if(!isPrime(i)) { //since we banned prime numbers from this process i don't include them
int for_digit_sum = i, digit = 0, digit_sum = 0, for_factor_purpose = i, smith_sum = 0;
int first = 0, second = 0, last = 0;
// System.out.println("current number is" + i);
while (for_digit_sum > 0) { // in this while loop i get the sum of current number's digits
digit = for_digit_sum % 10;
digit_sum += digit;
for_digit_sum /= 10;
}
// System.out.println("digit sum is"+digit_sum);
while (for_factor_purpose % 2 == 0) { // i divide the current number to 2 until it became an odd number
first += 2;
for_factor_purpose /= 2;
}
// System.out.println("the first sum is " + first);
for (int j = 3; j < Math.sqrt(for_factor_purpose); j += 2) {
while (for_factor_purpose % j == 0) { // this while loop is for getting the digit sum of every prime
// factor that j has
int inner_digit = 0, inner_temp = j, inner_digit_sum = 0;
while (inner_temp > 0) {
inner_digit = inner_temp % 10;
second += inner_digit;
inner_temp /= 10;
}
// System.out.println("the second sum is " + second);
for_factor_purpose /= j;
}
}
int last_temp = for_factor_purpose, last_digit = 0, last_digit_sum = 0;
if (for_factor_purpose > 2) {
while (last_temp > 0) {
last_digit = last_temp % 10;
last += last_digit;
last_temp /= 10;
}
// System.out.println("last is " + last);
}
smith_sum = first + second + last;
// System.out.println("smith num is "+ smith_sum);
// System.out.println(smith_sum);
if (smith_sum == digit_sum) {
System.out.println("the num founded is" + i);
}
}
}
}
public static boolean isPrime(int i) {
int sqrt = (int) Math.sqrt(i) + 1;
for (int k = 2; k < sqrt; k++) {
if (i % k == 0) {
// number is perfectly divisible - no prime
return false;
}
}
return true;
}
the output is:
the num founded is4
the num founded is9
the num founded is22
the num founded is25
the num founded is27
the num founded is49
how ever the smith number between this range(1 and 50) are:
4, 22 and 27
edit:I_ve found the problem which is :
Math.sqrt(for_factor_purpose) it seems i should add 1 to it to eliminate square numbers. Thanks to you guys i've see sthe solution on other perspectives.
Keep coding!
Main loop for printing Smith numbers.
for (int i = 3; i < 10000; i++) {
if (isSmith(i)) {
System.out.println(i + " is a Smith number.");
}
}
The test method to determine if the supplied number is a Smith number. The list of primes is only increased if the last prime is smaller in magnitude than the number under test.
static boolean isSmith(int v) {
int sum = 0;
int save = v;
int lastPrime = primes.get(primes.size() - 1);
if (lastPrime < v) {
genPrimes(v);
}
outer:
for (int p : primes) {
while (save > 1) {
if (save % p != 0) {
continue outer;
}
sum += sumOfDigits(p);
save /= p;
}
break;
}
return sum == sumOfDigits(v) && !primes.contains(v);
}
Helper method to sum the digits of a number.
static int sumOfDigits(int i) {
return String.valueOf(i).chars().map(c -> c - '0').sum();
}
And the prime generator. It uses the list as it is created to determine if a given
number is a prime.
static List<Integer> primes = new ArrayList<>(List.of(2, 3));
static void genPrimes(int max) {
int next = primes.get(primes.size() - 1);
outer:
while (next <= max) {
next += 2;
for (int p : primes) {
if (next % p == 0) {
continue outer;
}
if (p * p > next) {
break;
}
}
primes.add(next);
}
}
}
I do not want to spoil the answer finding, but just some simpler code snippets,
making everything simpler, and more readable.
public boolean isSmith(int a) {
if (a < 2) return false;
int factor = findDivisor(a);
if (factor == a) return false;
int sum = digitSum(a);
// loop:
a /= factor;
sum -= digitSum(factor);
...
}
boolean isPrime(int a){
for(int i = 2; i*i <= a; i++) {
if (a % i == 0) {
return false;
}
}
return true;
}
int findDivisor(int a){
for(int i = 2; i*i <= a; i++) {
if (a % i == 0) {
return i;
}
}
return a;
}
int digitSum(int a) {
if (a < 10) {
return a;
}
int digit = a % 10;
int rest = a / 10;
return digit + digitSum(rest);
}
As you see integer division 23 / 10 == 2, and modulo (remainder) %: 23 % 10 == 3 can simplify things.
Instead of isPrime, finding factor(s) is more logical. In fact the best solution is not using findDivisor, but immediately find all factors
int factorsSum = 0;
int factorsCount = 0;
for(int i = 2; i*i <= a; i++) {
while (a % i == 0) {
factorsSum += digitSum(i);
a /= i;
factorsCount++;
}
}
// The remaining factor >= sqrt(original a) must be a prime.
// (It cannot contain smaller factors.)
factorsSum += digitSum(a);
factorsCount++;
Here is the code. If you need further help, please let me know. The code is pretty self explanatory and a decent bit was taken from your code but if you need me to explain it let me know.
In short, I created methods to check if a number is a smith number and then checked each int in the range.
import java.util.*;
public class MyClass {
public static void main(String args[]) {
System.out.println(smithInRange)
}
public int factor;
public boolean smithInRange(int a, int b){
for (int i=Math.min(a,b);i<=Math.max(a,b);i++) if(isSmith(i)) return true;
return false;
}
public boolean isSmith(int a){
if(a<2) return false;
if(isPrime(a)) return false;
int digits=0;
int factors=0;
String x=a+¨" ";
for(int i=0;i<x.length()-1;i++) digits+= Integer.parseInt(x.substring(i,i+1));
ArrayList<Integer> pF = new ArrayList<Integer>();
pF.add(a);
while(!aIsPrime(pF)){
int num = pF.get(pF.size-1)
pF.remove(pF.size()-1);
pF.add(factor);
pF.add(num/factor)
}
for(int i: pF){
if((factors+"").length()==1)factors+= i;
else{
String ss= i+" ";
int nums=0;
for(int j=0;j<ss.length()-1;j++){
nums+=Integer.parseInt(ss.substring(j,j+1));
}
}
}
return (factors==digits);
}
public boolean isPrime(int a){
for(int i=2;i<=(int)Math.sqrt(a),i++){
String s = (double)a/(double)i+"";
if(s.substring(s.length()-2).equals(".0")){
return false;
factor = i;
}
}
return true;
}
public boolean aIsPrime(ArrayList<int> a){
for(int i: a) if (!isPrime(a)) return false;
return true;
}
}

Java binary multiplication using integer arrays not working

I'm making a program that accepts two decimal numbers and convert them into binary numbers, which are stored in integer arrays. Then I need to do multiplication using the two integer arrays. The result should also be a binary integer array (I need to validate that using a for loop). Then I convert them result to decimal number.
So far, I have the following code. My logic to convert the decimal number to binary works fine and vice verse. However, the binary result is always somehow smaller than the expected result. I have spent a lot of time on this, could you help me check what is wrong?
public class BinaryMultiplication {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int num1 = scanner.nextInt();
int num2 = scanner.nextInt();
int[] binaryNum1 = toBinary(num1);
int[] binaryNum2 = toBinary(num2);
System.out.println("Expected result: " + num1 * num2);
System.out.println("Decimal number 1: " + toDecimal(binaryNum1));
System.out.println("Decimal number 2: " + toDecimal(binaryNum2));
int[] resultBinaries = new int[100];
for (int i = 0; i < resultBinaries.length; ++i) {
resultBinaries[i] = 0;
}
for (int i = 0; binaryNum1[i] != -1; ++i) {
for (int j = 0; binaryNum2[j] != -1; ++j) {
resultBinaries[i + j] += binaryNum1[i] * binaryNum2[j] % 2;
resultBinaries[i + j] %= 2;
}
}
resultBinaries[99] = -1;
for (int i = 0; resultBinaries[i] != -1; ++i) {
if (resultBinaries[i] > 1) {
System.out.println("The result is not a binary!!");
}
}
System.out.println("Actual decimal result: " + toDecimal(resultBinaries));
}
public static int toDecimal(int[] binaryNum) {
int result = 0;
int factor = 1;
for (int i = 0; binaryNum[i] != -1; ++i) {
result += binaryNum[i] * factor;
factor *= 2;
}
return result;
}
public static int[] toBinary(int num) {
int[] binaries = new int[100];
int index = 0;
while (num > 0) {
binaries[index++] = num % 2;
num /= 2;
}
binaries[index] = -1;
return binaries;
}
}
A sample input & output: ( the binary validation loop works fine)
45 67
Expected result: 3015
Decimal number 1: 45
Decimal number 2: 67
Actual decimal result: 2871
for (int i = 0; binaryNum1[i] != -1; ++i) {
for (int j = 0; binaryNum2[j] != -1; ++j) {
resultBinaries[i + j] += binaryNum1[i] * binaryNum2[j] % 2;
resultBinaries[i + j] %= 2;
}
}
What happens when resultBinaries[i + j] increases to 2? It's reduced to 0 and then resultBinaries[i + j + 1] should be increased with 1, but this isn't happening in the code as far as I can see.

Modification of sieve of eratosthenes, time and space complexity check

I understand the time complexity for the 'sieve of eratosthenes' algorithm to be O(n log log n). I have modified this algorithm such that my sieve will always be of size 100. I will keep looping over next 100 numbers if I do not find the next prime. How would I explain the time-complexity And Space complexity of getNthPrime and getNextPrime methods ?
A snippet:
public class PrimeUtil {
private static final boolean COMPOSITE = true;
private static final int DEFAULT_SIZE = 100;
// cache of primes.
public final List<Integer> primes;
public int cachedMaxPrime;
public PrimeUtil() {
primes = new ArrayList<Integer>();
// initial seed
primes.addAll(Arrays.asList(2, 3, 5, 7, 11, 13));
cachedMaxPrime = primes.get(primes.size() - 1);
}
private void validate(int n) {
if (n <= 0) {
throw new IllegalArgumentException("Expecting a non-zero value");
}
}
public synchronized int getNthPrime(int nThPrime) {
validate(nThPrime);
if (nThPrime <= primes.size()) {
return primes.get(nThPrime - 1);
}
int n = DEFAULT_SIZE; // find all primes for next 100 numbers.
while (primes.size() < nThPrime) {
computePrimesUptoN(n);
n += DEFAULT_SIZE; // find all primts for next 100 numbers.
}
return primes.get(nThPrime - 1);
}
public synchronized int getNextPrime(int prime) {
validate(prime);
int primeIndex = Collections.binarySearch(primes, prime);
if (primeIndex != -1 && primeIndex != (primes.size() - 1)) {
return primes.get(primeIndex + 1);
}
int prevSize = primes.size();
int n = DEFAULT_SIZE; // adding cachedMaxPrime to DEFAULT_SIZE is a tiny optimization, nothing else.
while (primes.size() == prevSize) {
computePrimesUptoN(n);
n += DEFAULT_SIZE;
}
return primes.get(primeIndex + 1);
}
private List<Integer> computePrimesUptoN(int n) {
boolean[] composites = new boolean[n - cachedMaxPrime]; //
int root = (int)Math.sqrt(n); // root is sqrt(50) ie 7.
for (int i = 1; i < primes.size() && primes.get(i) <= root; i++) { // will loop until prime = 7.
int prime = primes.get(i); // first prime: 3
int firstPrimeMultiple = (cachedMaxPrime + prime) - ((cachedMaxPrime + prime) % prime);
if (firstPrimeMultiple % 2 == 0) {
firstPrimeMultiple += prime;
}
filterComposites(composites, prime, firstPrimeMultiple, n);
}
// loop through all primes in the range of max-cached-primes upto root.
for (int prime = cachedMaxPrime + 2; prime < root; prime = prime + 2) {
if (!composites[prime]) {
// selecting all the prime numbers.
filterComposites(composites, prime, prime, n);
}
}
for (int i = 1; i < composites.length; i = i + 2) {
if (!composites[i]) {
primes.add(i + (cachedMaxPrime + 1));
}
}
cachedMaxPrime = primes.get(primes.size() - 1);
return primes;
}
private void filterComposites(boolean[] composites, int prime, int firstMultiple, int n) {
for (int multiple = firstMultiple; multiple < n; multiple += prime + prime) {
composites[multiple - (cachedMaxPrime + 1)] = COMPOSITE;
}
}
}

Generating two random prime numbers in JAVA

I'm trying to generate two random prime numbers in JAVA, however, I want the loop to keep repeating itself until both of those two variables are prime numbers, and then they output themselves.
The p and q variables are randomized by the Math.random() function and are in the range of 2 to 128 (excluding the 128).
Here is my code:
int pRandom = (int) (Math.random() * (127 - 2) + 2);
int qRandom = (int) (Math.random() * (127 - 2) + 2);
int p = pRandom;
int q = qRandom;
for (int i = 1; i < p; i++) {
boolean isPPrime = true;
for (int j = 2; j < i; j++) {
if (i % j == 0) {
isPPrime = false;
break;
}
}
if (isPPrime){
JOptionPane.showMessageDialog(null, "YAY!");
break;
}
System.out.println("P value: " + p + "\n" + "Q value: " + q);
}
Here is what you want:
public class RandomPrimeGenerator {
public static void main(String[] args) {
while (true) {
int pRandom = (int) (Math.random() * (127 - 2) + 2);
if(isPrime(pRandom)){
System.out.println("Got Random Prime P :"+pRandom);
break;
}
}
while(true){
int qRandom = (int) (Math.random() * (127 - 2) + 2);
if(isPrime(qRandom)){
System.out.println("Got Random Prime Q :"+qRandom);
break;
}
}
}
private static boolean isPrime(int n) {
int i;
for(i=2;i<=Math.sqrt(n);i++){
if(n % i == 0){
return false;
}
}
return true;
}
}

Check Credit Card Validity using Luhn Algorithm

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));

Categories