Luhn Check program in Java not calculating correctly - java

I created this Luhn Check (or Mod 10 check) in Java and the Even and Odd sums aren't adding up correctly and I can't figure out why. It worked when I wrote that one section out separately and it seemed to work fine. As a whole program with all the other Methods it doesn't work. Anyone have any ideas?
Entering the number 4388576018410707 should be valid.
import java.util.Scanner;
import java.io.*;
public class combineAll {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Enter a credit card number: ");
long userInput = input.nextLong();
int getSize=getSize(userInput); //Run getSize() Method.
Integer z = (int) (long) getPrefix(userInput, getSize); //Run getPrefix() Method.
if (prefixMatch(userInput, z)== true) { //Run prefixMatch() Method.
long n=sumbOfDoubleEvenPlace(userInput); //Run sumbOfDoubleEvenPlace() Method.
long m=sumOfOddPlace(userInput); //Run sumOfOddPlace() Method.
System.out.println("Total Even: " +n);
System.out.println("Total Odd: " +m);
long v=n+m;
if (isValid(v)==true) {
System.out.println("Valid");
} else if (isValid(v)==false){
System.out.println("Invalid");
}
} else {
System.out.println("Invalid");
}
} //End main
//Return the number of digits in d
public static int getSize(long d) {
String str = Long.toString(d);
int x = str.length();
return x;
}
//Return the first k number of digits from number. If the number of digits in number is less than k, return number
public static long getPrefix(long number, int k) {
int z=0;
if (k>=13 && k<=16) {
String str = Long.toString(number);
String g = str.substring(0,1);
String h = str.substring(0,2);
int d=Integer.parseInt(g);
int q=Integer.parseInt(h);
if (d==4 || d==5 ||d==6) {
z=d;
} else if (q==37) {
z=q;
}
} else {
z=-1;
}
return z;
}
//Return true if the digit d is a prefix for number
public static boolean prefixMatch(long number, int d) {
if (d==4 || d==5 || d==6 || d==37) {
return true;
} else {
return false;
}
}
//Get the result from step 2
public static int sumbOfDoubleEvenPlace(long number) {
long a=number;
int d=0; //Adds each individual numbers.
while (a>0) {
long b=0;
long c=0; //Equals the Mod of UserInput.
a=a/10;
c=a%10;
System.out.println("even: " +c);
b=c*2;
if (b>=10) {
Integer digit = (int) (long) b;
d+=getDigit(digit); //Run getDigit() Method.
} else {
Integer digit = (int) (long) b;
d+=b;
}
a=a/10; //Advance decimal one space to the left.
}
return d;
}
//Return sum of odd-place digits in number
public static int sumOfOddPlace(long number) {
long a=number;
int d=0; //Adds each individual numbers.
while (a>0) {
long b=0;
long c=0; //Equals the Mod of UserInput.
c=a%10;
System.out.println("odd: " +c); //Print for debugging.
b=c*2;
if (b>=10) {
Integer digit = (int) (long) b;
d+=getDigit(digit); //Run getDigit() Method.
} else {
Integer digit = (int) (long) b;
d+=b;
}
a=a/10; //Advance decimal one space to the left.
a=a/10;
}
return d;
}
//Return this number if it is a single digit, otherwise return the sum of the two digits
public static int getDigit(int number) {
int d=0;
int x=0;
int y=number;
while (y>0) {
x+=y%10;
y=y/10;
}
return x;
}
//Return true if the card number is valid
public static boolean isValid(long number) {
long c=number%10;
if (c==0) {
return true;
} else {
return false;
}
}
}

The code is a little hard to follow. Based on the algorithm description form Wikipedia the implementation should be much simpler.
Here is other implementation following the description from Wikipedia.
public class Cards {
/**
* Checks if the card is valid
*
* #param card
* {#link String} card number
* #return result {#link boolean} true of false
*/
public static boolean luhnCheck(String card) {
if (card == null)
return false;
char checkDigit = card.charAt(card.length() - 1);
String digit = calculateCheckDigit(card.substring(0, card.length() - 1));
return checkDigit == digit.charAt(0);
}
/**
* Calculates the last digits for the card number received as parameter
*
* #param card
* {#link String} number
* #return {#link String} the check digit
*/
public static String calculateCheckDigit(String card) {
if (card == null)
return null;
String digit;
/* convert to array of int for simplicity */
int[] digits = new int[card.length()];
for (int i = 0; i < card.length(); i++) {
digits[i] = Character.getNumericValue(card.charAt(i));
}
/* double every other starting from right - jumping from 2 in 2 */
for (int i = digits.length - 1; i >= 0; i -= 2) {
digits[i] += digits[i];
/* taking the sum of digits grater than 10 - simple trick by substract 9 */
if (digits[i] >= 10) {
digits[i] = digits[i] - 9;
}
}
int sum = 0;
for (int i = 0; i < digits.length; i++) {
sum += digits[i];
}
/* multiply by 9 step */
sum = sum * 9;
/* convert to string to be easier to take the last digit */
digit = sum + "";
return digit.substring(digit.length() - 1);
}
public static void main(String[] args) {
String pan = "4388576018410707";
System.out.println("Validate pan number '" + pan + "': " + luhnCheck(pan2));
}
}

Related

Java setMethod dose not work. When I pass the value to the setMethod it doesn't pass it to line

I have a Result class in which I keep all values/results.
All my code:
public class Main {
public static void main(String[] args) {
Main main = new Main();
Result result = new Result();
Divider divider = new Divider();
String[] myTestArray = new String[]{"1234", "12"};
if (myTestArray.length != 2) {
System.out.printf("You can not use %d arguments. " +
"To perform division, you need to use 2 arguments `", myTestArray.length);`
System.exit(1);
}
int dividend = Integer.parseInt(myTestArray[0]);
int divisor = Integer.parseInt(myTestArray[1]);
divider.divide(dividend, divisor);
Formatter formatter = new Formatter();
formatter.format(result);
}
}
public class Divider {
Result result;
public Divider() {
this.result = new Result();
}
/**
* divide method performs division of two numbers
*/
public void divide(int dividend, int divisor) {
result.setDividend(Math.abs(dividend));
result.setDivisor(Math.abs(divisor));
result.setQuotient(divideTwoNumbers(result.getDividend(),
result.getDivisor()));
}
/**
*
*/
public int calculateProduct(int partialDividend) {
int multiplicand = divideTwoNumbers(partialDividend, `result.getDivisor());`
result.setProduct(multipleTwoNumbers(result.getDivisor(), `multiplicand));`
result.setRemainder(partialDividend - result.getProduct());
return result.getProduct();
}
/**
* Method divideTwoNumbers is used instead of operands "/"
*/
public int divideTwoNumbers(int dividend, int divisor) {
int result = 0;
for (int i = 0; dividend >= divisor; i++) {
dividend = dividend - divisor;
result++;
}
return result;
}
/**
* Method multipleTwoNumbers is used instead of operands "*"
*/
public int multipleTwoNumbers(int multiplicand, int multiplier) {
int product = 0;
for (int i = 0; i < multiplicand; i++) {
product = product + multiplier;
}
return product;
}
}
I think, my problem is around here somewhere
public class Formatter {
Result result;
Divider divider;
private int firstIndexPartialDividend = 0; // find the beginning of the number
private int countSpace = 0; // space counter
public Formatter() {
this.result = new Result();
this.divider = new Divider();
}
public void format() {
// print the first row
printFirstRow();
String dividendText = Integer.toString(result.getDividend());
for (int i = 1; i <= dividendText.length(); i++) {
result.setFirstPartialDividend(Integer.parseInt
(dividendText.substring(firstIndexPartialDividend, i)));
// print the second row
if (result.getFirstPartialDividend() >= result.getDivisor() &&
firstIndexPartialDividend == 0) {
countSpace = dividendText.length() - i;
printSecondRow(result.getFirstPartialDividend());
firstIndexPartialDividend = i;
// To align the space in the next row.
if (Integer.toString(result.getProduct()).length()
> Integer.toString(result.getRemainder()).length() &&
result.getRemainder() > 0) {
countSpace = Integer.toString(result.getProduct()).length()
- Integer.toString(result.getRemainder()).length();
} else {
countSpace = 0;
}
}
}
}
/**
* printFirstRow method - print the first row of an application
*/
public void printFirstRow() {
System.out.printf("%d|%d\n", result.getDividend(), `enter code here`result.getDivisor());
}
/**
* printSecondRow method - print the second row of an application
*/
public void printSecondRow(int firstPartialDividend) {
divider.calculateProduct(firstPartialDividend);
System.out.println(result.getProduct() + getSpace(countSpace) + `enter code here`"|" + (result.getQuotient()));
}
/**
* getSpace method to get the number of spaces you want
*/
public String getSpace(int count) {
String space = "";
for (int i = 0; i < count; i++)
space += " ";
return space;
}
}
public class Result {
private int quotient; // keep the result of division
private int dividend;
private int divisor;
private int firstPartialDividend; //keep the result of division the `enter code here`first partial dividend
private int product;
private int remainder;
`enter code here`public Result() {
this.dividend = dividend;
this.divisor = divisor;
}
public int getQuotient() {
return quotient;
}
public void setQuotient(int quotient) {
this.quotient = quotient;
}
public int getDividend() {
return dividend;
}
public void setDividend(int dividend) {
this.dividend = dividend;
}
public int getDivisor() {
return divisor;
}
public void setDivisor(int divisor) {
this.divisor = divisor;
}
public int getFirstPartialDividend() {
return firstPartialDividend;
}
public void setFirstPartialDividend(int firstPartialDividend) {
this.firstPartialDividend = firstPartialDividend;
}
public int getProduct() {
return product;
}
public void setProduct(int product) {
this.product = product;
}
public int getRemainder() {
return remainder;
}
public void setRemainder(int remainder) {
this.remainder = remainder;
}
}
values are still 0
My program should print long division result
Like this:
1234|12
12 |102
34
24
10
Of course this is not the whole program, I am still working on it.
The image shown has stopped before the assignment is complete. The parameter value is 1234, and the current value of this.dividend is zero. If you step the debugger forward, both will have the value of 1234
Your setters are working fine. You are just not calling the setters on the correct instances.
Regarding the "issue". You have a Result and Divider instance in main method that is not given to the Formatter. When you create a new Formatter() it has its own instances that are initialized with the default values of zero.
You probably should have a constructors that carry through the same instances. For example
Result result = new Result(); // this probably isn't even needed
Divider divider = new Divider(result); // param could be removed
divider.divide(x1, x2); // This method could create and store `new Result()` value on its own
Formatter formatter = new Formatter(divider, result); // again, result not needed since it would be internal to the divider
formatter.format();
(and your formatter should probably only "format the result" as the name implies instead of also doing calculations with the Divider instance)
You can also remove new Main() since that isn't doing anything
OneCricketeer - thanks a lot!!!
I has changed constructor Divider and Formatter.
Result result = new Result();
Divider divider = new Divider(result);
divider.divide(dividend, divisor);
Formatter formatter = new Formatter(result);
formatter.format();
public Divider(Result result) {
this.result = result;
}
public Formatter(Result result) {
this.result = result;
this.divider = new Divider(result);
}
Now my output is
1234|12
12 |102

Java StringToNUMBER - return 0 if the string contains anything other than digits and an initial "-" for negative numbers

I have to implement the following function in Java: public int stringToNumber(String input) without using Integer or any other class or method that parses the string. I have to loop over the characters of the string.
I attempted created a class that uses a loop to convert String to Integer.
Now, I am trying to figure out how I can return 0 if the string contains anything other than digits and an initial "-" for negative numbers.
Also I am trying to return 0 if the number is too large or too small for an int (Integer.MIN_SIZE to Integer.MAX_SIZE or -2^31 to 2^31 - 1).
Below is the code that I have so far.... Any help would be greatly appreciated
public class StringToNumber {
public static void main(String[] args) {
StringToNumber stn = new StringToNumber();
for (String arg : args) {
int number = stn.stringToNumber(arg);
System.out.format("Input number: %s, parsed number: %d %n", arg, number);
}
}
public int stringToNumber(String stn) {
int number = 0, factor = 1;
for (int n = stn.length()-1; n >= 0; n--) {
number += (stn.charAt(n) - '0') * factor;
factor *= 10;
}
return number;
}
}
Check if below code is working for you
public int stringToNumber(String stn) {
int number = 0, factor = 1;
int negative = 0;
if(stn.charAt(0)=='-') {
negative =1;
}
for (int n = negative; n < stn.length(); n++) {
int digit = stn.charAt(n)-'0';
if(digit<0 || digit>9)
return 0;
if((negative==0) && (Integer.MAX_VALUE-digit)/10 <number)
return 0;
else if ((negative==1) && (Integer.MAX_VALUE-digit+1)/10 <number)
return 0;
number = number*10+ (stn.charAt(n)-'0');
}
if(negative == 1) {
return -1*number;
}
return number;
}
Perhaps the best way to handle this would be to use Integer#parseInt(), which takes a string input and either returns an integer result or throws an exception if the input cannot be coerced to an integer:
public int stringToNumber(String stn) {
int result;
try {
result = Integer.parseInt(stn);
}
catch (NumberFormatException e) {
System.out.println("String input cannot be converted to integer: " + stn);
result = 0; // return 0 as the failure value
}
return result;
}

How to print out a toString for this class?

I have written a polynomial class and a tester class. The polynomial class can evaluate and return the sum of the polynomial when the degree, coefficients and the value of x are provided. Basically I need to edit my toString method so it actually prints out the polynomial
import java.util.Arrays;
import java.util.Scanner;
public class Polynomial {
private int degree;
private int [] coefficient;
private double evaluation;
private double sum;
private double value;
Scanner key = new Scanner(System.in);
public Polynomial(int degree)
{
this.degree = degree;
coefficient = new int [degree+1];
}
public void setCoefficient(int coefficient)
{
this.coefficient[this.degree] = coefficient;
}
public int getCoefficient(int degree)
{
return coefficient[degree];
}
public double Evaluate(double value)
{
this.value =value;
for (int i=0; i<=degree; i++)
{
System.out.println("Enter coefficent for position " + i);
this.coefficient[i] = key.nextInt();
evaluation = Math.pow(value, i)*this.coefficient[0] ;
this.sum += evaluation;
}
return sum;
}
/** Standard toString method */
//needed something better than this below...needed an actual polynomial printed out
public String toString()
{
return "The degree of the polynomial is " + degree + " and the value for which it has been evaluated is" + value;
}
}
This should be along the lines you should be proceeding. I included the main function in your Polynomial class for simplicity, so you will have to modify that if you want to keep it in your tester class. Notice that degree has been made into an integer array of size degree +1(allocated in the constructor):
import java.util.Scanner;
public class Polynomial {
private int degree;
private int [] coefficient;
private double evaluation;
private double sum;
Scanner key = new Scanner(System.in);
public Polynomial(int degree)
{
this.degree = degree;
coefficient = new int [degree+1];
}
public void setCoefficient(int coefficient, int degree)
{
this.coefficient[degree] = coefficient;
}
public int getCoefficient(int degree)
{
return coefficient[degree];
}
public void Evaluate(double value)
{
for (int i=0; i<=degree; i++)
{
System.out.println("Enter coefficent for position " + i);
this.coefficient[i] = key.nextInt();
evaluation = Math.pow(value, i)*this.coefficient[0] ;
this.sum += evaluation;
}
}
public double getSum(){
return sum;
}
public String toString()
{
String s = "";
for (int i=0; i <= degree; i++)
{
s += coefficient[i];
switch (i) {
case 0:
s += " + ";
break;
case 1:
s += "x + ";
break;
default:
s += "x^" + i + ((i==degree)?"":" + ");
}
}
return s;
}
public static void main(String[] args) {
int degree;
double sum;
int coefficient;
Scanner key = new Scanner(System.in);
System.out.println("Enter the degree of the polynomial");
degree=key.nextInt();
Polynomial fun = new Polynomial(degree);
fun.Evaluate(3.0);
System.out.println(" The sum of the polynomial is " + fun.getSum());
System.out.println(fun);
}
}
The usual way of making the objects of a class printable is to supply a toString method in the class, which specifies how to express objects of that class as a String. Methods such as println and other ways of outputting a value will call a class's toString method if they need to print an object of that class.
You should adopt the same pattern with your Polynomial class - write a toString method with all the output logic. Then in your PolynomialTester class, all you need to write is System.out.println(fun); and the rest will just happen. You'll find this far more versatile than writing a method that actually does the printing. For example, you'll be able to write something like
System.out.println("My polynomial is " + fun + " and " + fun + " is my polynomial.");
if that's your idea of fun.
A few other things concern me about your class.
You seem to be only storing one coefficient and one exponent. I'd expect a polynomial to have a whole array of coefficients.
You have fields for evaluation and sum - but these only really make sense while a polynomial is being evaluated. They're not long-term properties of the polynomial. So don't store them in fields. Have them as local variables of the evaluate method, and return the result of the evaluation.
I'd expect a class like this to be immutable. That is, you should provide all the coefficients when the object is created, and just never change them thereafter. If you do it that way, there's no need to write setter methods.
So I've written my own version of your class, that fixes those issues listed above, and implements a toString method that you can use for printing it. A second version of toString lets you specify which letter you want to use for x. I've used "varargs" in the constructor, so you can construct your polynomial with a line such as
Polynomial fun = new Polynomial (7, 2, 5, 0, 1);
specifying the coefficients from the constant term through in order to the coefficient of the term with the highest exponent. Or you can just pass an array.
See that I've changed the logic a wee bit - my version prints the polynomial in the conventional order, from highest to lowest exponent. It leaves off the decimals if the coefficient is an integer. It doesn't print a 1 in front of an x. And it deals cleanly with - signs.
import java.util.Arrays;
public class Polynomial {
private double[] coefficients;
public Polynomial(double... coefficients) {
this.coefficients = Arrays.copyOf(coefficients, coefficients.length);
}
public int getDegree() {
int biggestExponent = coefficients.length - 1;
while(biggestExponent > 0 && coefficients[biggestExponent] == 0.0) {
biggestExponent--;
}
return biggestExponent;
}
public double getCoefficient(int exponent) {
if (exponent < 0 || exponent > getDegree()) {
return 0.0;
} else {
return coefficients[exponent];
}
}
public double evaluateAt(double x) {
double toReturn = 0.0;
for (int term = 0; term < coefficients.length; term++) {
toReturn += coefficients[term] * Math.pow(x, term);
}
return toReturn;
}
#Override
public String toString() {
return toString('x');
}
public String toString(char variable) {
boolean anythingAppendedYet = false;
StringBuilder toReturn = new StringBuilder();
for (int exponent = coefficients.length - 1; exponent >= 0; exponent--) {
if (coefficients[exponent] != 0.0) {
appendSign(toReturn, exponent, anythingAppendedYet);
appendNumberPart(toReturn, exponent);
appendLetterAndExponent(toReturn, exponent, variable);
anythingAppendedYet = true;
}
}
if (anythingAppendedYet) {
return toReturn.toString();
} else {
return "0";
}
}
private void appendSign(StringBuilder toAppendTo, int exponent, boolean anythingAppendedYet) {
if (coefficients[exponent] < 0) {
toAppendTo.append(" - ");
} else if (anythingAppendedYet) {
toAppendTo.append(" + ");
}
}
private void appendNumberPart(StringBuilder toAppendTo, int exponent) {
double numberPart = Math.abs(coefficients[exponent]);
if (numberPart != 1.0 || exponent == 0) {
//Don't print 1 in front of the letter, but do print 1 if it's the constant term.
if (numberPart == Math.rint(numberPart)) {
// Coefficient is an integer, so don't show decimals
toAppendTo.append((long) numberPart);
} else {
toAppendTo.append(numberPart);
}
}
}
private void appendLetterAndExponent(StringBuilder toAppendTo, int exponent, char variable) {
if (exponent > 0) {
toAppendTo.append(variable);
}
if (exponent > 1) {
toAppendTo.append("^");
toAppendTo.append(exponent);
}
}
}
So I tested it with this class
public class PolynomialTester {
public static void main(String[] args) {
Polynomial fun = new Polynomial (7, 2, 5, 0, 1);
System.out.println(fun.getDegree());
System.out.println(fun.evaluateAt(3));
System.out.println(fun);
}
}
and the output was
4
139.0
x^4 + 5x^2 + 2x + 7
then I realised that you wanted to be able to input the coefficients in a loop. So I changed PolynomialTester to this. See how I build the array and then create the object.
import java.util.Scanner;
public class PolynomialTester {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Enter the degree:");
int degree = input.nextInt();
double[] coefficients = new double[degree + 1];
for( int exponent = 0; exponent <= degree; exponent++) {
System.out.println("Enter the coefficient of x^" + exponent);
coefficients[exponent] = input.nextDouble();
}
Polynomial fun = new Polynomial (coefficients);
System.out.println(fun.evaluateAt(3));
System.out.println(fun);
input.close();
}
}
Note that if you really want your polynomial to be printed in "reverse" order, with the constant term first, you could change the loop in the toString method to this.
for (int exponent = 0; exponent < coefficients.length; exponent++) {
You may add a class member String poly, then modify the following method.
public void Evaluate(double value)
{
for (int i=0; i<=degree; i++)
{
System.out.println("Enter coefficent for position " + i);
this.coefficient= key.nextInt();
evaluation = Math.pow(value, i)*coefficient ;
this.sum += evaluation;
this.poly = "";
if(coefficient != 0)
{
if(i > 0)
{
this.poly += " + " + Integer.toString(coefficient) + "x^" + Integer.toString(i); // you may replace x with the actual value if you want
}
else
{
this.poly = Integer.toString(coefficient)
}
}
}
}

Loop in Credit Card Validation in java

I am a high school student in an introductory Computer Science course. Our assignment was the following:
The last digit of a credit card number is the check digit, which protects against transcription errors such as an error in a single digit or switching two digits. the following method is used to verify actual credit card numbers but, for simplicity, we will describe it for numbers with 8 digits instead of 16:
Starting from the rightmost digit, form the sum of every other digit. For example, if the credit card number is 4358 9795, then you form the sum 5+7+8+3 = 23.
Double each of the digits that were not included in the preceding step. Add all the digits of the resulting numbers. For example, with the numbers given above, doubling the digits, starting with the next-to-last one, yields 18 18 10 8. Adding all the digits in these values yields 1+8+1+8+1+0+8=27.
Add the sums of the two preceding steps. If the last digit of the result is 0, the number is valid. In our case, 23 + 27 = 50, so the number is valid.
Write a program that implements this algorithm. The user should supply an 8-digit number, and you should print out whether the number is valid or not. If it is not valid, you should print out the value of the check digit that would make the number valid.
I have everything done except for the part in bold. My code is listed below:
public class CreditCard
{
private String creditCardNumber;
private boolean valid;
private int checkDigit;
int totalSum;
/**
* Constructor for objects of class CreditCard
*/
public CreditCard(String pCreditCardNumber)
{
creditCardNumber = pCreditCardNumber;
checkDigit = Integer.parseInt(pCreditCardNumber.substring(creditCardNumber.length() - 1));
int sumOfDigits = checkDigit + Integer.parseInt(pCreditCardNumber.substring(6,7)) + Integer.parseInt(pCreditCardNumber.substring(3,4)) + Integer.parseInt(pCreditCardNumber.substring(1,2));
int dig7 = Integer.parseInt(pCreditCardNumber.substring(7,8));
int dig5 = Integer.parseInt(pCreditCardNumber.substring(5,6));
int dig3 = Integer.parseInt(pCreditCardNumber.substring(2,3));
int dig1 = Integer.parseInt(pCreditCardNumber.substring(0,1));
String string7 = Integer.toString(dig7);
int doubledDig7a = Integer.parseInt(string7.substring(0));
int doubledDig7b = 0;
if (dig7 * 2 >= 10)
{
doubledDig7a = Integer.parseInt(string7.substring(0));
doubledDig7b = 0;
}
String string5 = Integer.toString(dig5);
int doubledDig5a = Integer.parseInt(string7.substring(0));
int doubledDig5b = 0;
if (dig5 * 2 >= 10)
{
doubledDig5a = Integer.parseInt(string5.substring(0));
doubledDig5b = 0;
}
String string3 = Integer.toString(dig3);
int doubledDig3a = Integer.parseInt(string3.substring(0));
int doubledDig3b = 0;
if (dig3 * 2 >= 10)
{
doubledDig3a = Integer.parseInt(string3.substring(0));
doubledDig3b = 0;
}
String string1 = Integer.toString(dig1);
int doubledDig1a = Integer.parseInt(string1.substring(0));
int doubledDig1b = 0;
if (dig1 * 2 >= 10)
{
doubledDig1a = Integer.parseInt(string1.substring(0));
doubledDig1b = 0;
}
int doubleDigits = doubledDig1a + doubledDig1b + doubledDig3a + doubledDig3b + doubledDig5a + doubledDig5b + doubledDig7a + doubledDig7b;
totalSum = sumOfDigits + doubleDigits;
if (totalSum % 10 == 0)
{
valid = true;
}
else
{
valid = false;
}
}
public void makeItValid()
{
while (totalSum % 10 != 0)
{
checkDigit--;
if (totalSum % 10 == 0)
{
break;
}
}
}
public boolean isItValid()
{
return valid;
}
}
The loop is what I am having issues with. I always end up in an infinite loop whenever it compiles. It looks like everything should work, though. It's supposed to decrease the value of the check Digit (not increase so I don't end up with a check digit of 10 or higher), and then add that number back into the total sum until the total sum is divisible by 10, and then the loop would end. Is the type of loop I'm using wrong? Any advice would be appreciated.
Your problem is that both of your loop conditions involve totalSum but you only change checkDigit.
while (totalSum % 10 != 0)
{
checkDigit--;
if (totalSum % 10 == 0)
{
break;
}
}
You either need to recalculate totalSum or change the condition to be based on checkDigit. If you want to loop and decrement like you are doing you will need to add a method that performs the algorithm and call it every time. The way you have your class outlined makes this very inconvenient because you don't convert the numbers.
public static int[] cardToNumbers(String cardText) {
// \D is regex for non-digits
cardText = cardText.replaceAll("\\D", "");
int[] cardNumbers = new int[cardText.length()];
// convert unicode to corresponding integers
for (int i = 0; i < cardText.length(); i++)
cardNumbers[i] = cardText.charAt(i) - '0';
return cardNumbers;
}
public static int calcTotalSum(int[] cardNumbers) {
int sum = 0;
/* "every other one" loops
*
* I recommend against the "mod 2 index" scheme
* i % 2 relies on the card number being even
* you can't have your code blow up with unusual inputs
*
*/
for (int i = cardNumbers.length - 1; i >= 0; i -= 2) {
sum += cardNumbers[i];
}
for (int i = cardNumbers.length - 2; i >= 0; i -= 2) {
int dig = cardNumbers[i] * 2;
while (dig > 0) {
sum += dig % 10;
dig /= 10;
}
}
return sum;
}
Now you can do something like:
public void makeItValid() {
int[] invalidNumbers = cardToNumbers(creditCardNumber);
int sum = calcTotalSum(invalidNumbers);
while ((sum = calcTotalSum(invalidNumbers)) % 10 != 0)
invalidNumbers[invalidNumbers.length - 1]--;
totalSum = sum;
checkDigit = invalidNumbers[invalidNumbers.length - 1];
}
But you should be able to just subtract the difference to find the valid check digit:
if (totalSum % 10 != 0) checkDigit -= totalSum % 10;
Or something like:
public void makeItValid() {
int[] invalidNumbers = cardToNumbers(creditCardNumber);
checkDigit = invalidNumbers[invalidNumbers.length - 1] -= totalSum % 10;
totalSum = calcTotalSum(invalidNumbers);
valid = true;
}
Some asides,
I would recommend storing the digits as a field and have checkDigit represent an index in the array. This would simplify some of the operations you are doing.
I would also suggest not to be "silently" changing fields internally IE like in your makeItValid method unless this is a specification of the assignment. I think a better form is to let the "owning" code make the changes itself which is more clear externally. A somewhat complete implementation would look like this:
public class CreditCard {
public static void main(String[] args) {
if (args.length == 0) return;
CreditCard card = new CreditCard(args[0]);
if (!card.isValidNumber()) {
card.setCheckDigit(card.getValidCheckDigit());
}
}
private final String cardText;
private final int[] cardDigits;
private final int cdIndex;
public CreditCard(String ct) {
cardDigits = cardToNumbers(cardText = ct);
if ((cdIndex = cardDigits.length - 1) < 0) {
throw new IllegalArgumentException("# had no digits");
}
}
public boolean isValidNumber() {
return calcTotalSum(cardDigits) % 10 == 0;
}
public void setCheckDigit(int dig) {
cardDigits[cdIndex] = dig;
}
public int getValidCheckDigit() {
int sum = calcTotalSum(cardDigits);
if (sum % 10 != 0) {
return cardNumbers[cdIndex] - sum % 10;
} else {
return cardNumbers[cdIndex];
}
}
// above static methods
}
The best form IMO would be to disallow creation of a credit card object at all unless the check digit is valid. As an OOP principle it should not make sense to create invalid credit cards. The constructor should throw an exception if the card is invalid and have a static method to correct the number.
I would do something like the following (shortened):
public class CreditCard {
public CreditCard(String number) {
if (!validateCheckDigit(number)) {
throw new IllegalArgumentException("check digit failure");
}
}
}
public static void main(String[] args) {
String number = args[0];
CreditCard card = null;
boolean valid = false;
do {
try {
card = new CreditCard(number);
valid = true;
} catch (IllegalArgumentException e) {
number = CreditCard.correctCheckDigit(number);
}
} while (!valid);
}
I guess that's more or less doing your homework for you but I'm sure you can learn from it.
Unless I'm missing something major on how the validation works your makeitvalid method wont work in the way you are approaching it.
It makes more sense (at least to me) to extract everything you have in your constructor into a method ie.
boolean isValid(String cardNumber);
which would do everything that your constructor does except set the valid flag. your constructor then becomes
public CreditCard(String pCreditCardNumber){
valid = isValid(pCreditCardNumber);
}
and then to find what change would make it valid your check valid method does something like
change the value of check digit
if (isValid(Changed String))
return checkdigit
else
continue
repeat until you either find one that works or until you determine that it can't work.
Something along these lines should do. You'll still need to implement a few methods on your own.
public static void main(String[] args) {
String creditCardNumber = readCreditCardNumber();
String correctCreditCardNumber = getCorrectCreditCardNumber(creditCardNumber);
if (creditCardNumber.equals(correctCreditCardNumber)) {
System.out.println("Credit Card Valid");
} else {
System.out.println("Credit Card Invalid. Did you mean " + correctCreditCardNumber + "?");
}
}
public static String getCorrectCreditCardNumber(String creditCardNumber) {
int[] creditCardDigits = getCreditCardDigits(creditCardNumber);
int sum = 0;
for (int i = creditCardDigits.length - 2; i >= 0; i--) {
if (isOdd(i)) {
sum += creditCardDigits[i];
} else {
sum += digitSum(creditCardDigits[i] * 2);
}
}
int last = creditCardDigits.length - 1;
int remainder = sum % 10;
if (remainder != 0) {
creditCardDigits[last] = 10 - remainder;
}
return getCreditCardNumberAsString(creditCardDigits);
}
This program is very dynamic. I did not add too much error handling. You can enter any number that is divisible by 8.
Code in action:
Enter a card number: 4358 9795
Number is valid?: true
Continue? (y/n): y
Enter a card number: 4358 9796
Number is valid?: false
Continue? (y/n): y
Enter a card number: 43-58 97-95
Number is valid?: true
Continue? (y/n): n
Exiting...
CreditCardValidator.java
import java.text.ParseException;
import java.util.Scanner;
public class CreditCardValidator {
Integer[] digits;
public CreditCardValidator(String numberSequence) {
parseNumber(numberSequence);
}
private void parseNumber(String numberSequence) {
try {
String sequence = numberSequence.replaceAll("[\\s-]+", "");
int length = sequence.length();
if (length % 8 != 0) {
throw new IllegalArgumentException("Number length invalid.");
}
digits = new Integer[length];
int pos = 0;
for (Character c : sequence.toCharArray()) {
if (Character.isDigit(c)) {
digits[pos++] = Character.getNumericValue(c);
} else {
throw new ParseException("Invalid digit.", pos);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private boolean validateNumber() {
int sum = 0;
for (int i = digits.length - 1; i >= 0; i--) {
if (i % 2 == 1) {
sum += digits[i];
} else {
sum += NumberUtils.sumDigits(digits[i] * 2);
}
}
return sum % 10 == 0;
}
public static void main(String[] args) {
boolean stop = false;
CreditCardValidator c;
while (!stop) {
System.out.print("Enter a card number: ");
c = new CreditCardValidator(new Scanner(System.in).nextLine());
System.out.println("Number is valid?: " + c.validateNumber());
System.out.print("\nContinue? (y/n): ");
if (new Scanner(System.in).next().charAt(0) == 'n') {
stop = true;
}
System.out.println();
}
System.out.println("Exiting...");
System.exit(0);
}
}
I wrote a separate digit summation utility:
public class NumberUtils {
public static void main(String[] args) {
for(int i = 0; i < 2000; i+=75) {
System.out.printf("%04d: %02d\n", i, sumDigits(i));
}
}
public static int sumDigits(int n) {
if (n < 0)
return 0;
return sumDigitsRecursive(n, 0);
}
private static int sumDigitsRecursive(int n, int total) {
if (n < 10)
return total + n;
else {
return sumDigitsRecursive(n / 10, total + (n % 10));
}
}
}

How could I change my code to accept double values from the user?

import java.util.Scanner;
class MyCalculator {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.println("Enter a expression : ");
while(input.hasNext()){
String exp = input.next();
System.out.println(""+exp+" = "+ Calculate(exp));
}
}
//define a method to decide the operators' priority
private static int priority(char input){
switch(input){
case'(' : return 3; //parenthesis have highest priority
case')' : return 3;
case'*' : return 2; //multiplication and division have lower priority than parenthesis
case'/' : return 2;
case'+' : return 1; //plus minus have lowest operator priority
case'-' : return 1;
default : return 0;//numbers have lowest priority
}
}
//now we define our big method Calculate
public static int Calculate(String exp){
//firstly we try to check if the exp is already a number or a simple expression
//or having high level operator
//the key recursive idea is to compute inner results if there is higher level operators
//until the result is return
char[] inputs = exp.toCharArray();//we process string to char arrays for easy control
//now we check the highest level operators and the count
int highestPriority =0;
int operatorCount =0;//this value is to keep track of how many operators remaining, mostly to deal with negative number cases
for(int i=0;i<inputs.length;i++)
{
if(priority(inputs[i])>highestPriority)
{
highestPriority = priority(inputs[i]);//update highest priority if necessary
}
if(priority(inputs[i])>0)
{
++operatorCount;
}
}
//after that we process in order
if(operatorCount==0)//no operator remaining
{
return Integer.parseInt(exp);//Immediately return the result
}
else if(highestPriority==1){//-+ remaining
//we firstly deal with the negative numbers
if(operatorCount==1 && inputs[0]=='-')//if only operator is the leading minus operator
{
return Integer.parseInt(exp);
}
//otherwise, we need to find the operatorand compute result
int opePosition = -1;//set as -1 as non set
boolean ifPlusSign = true;//this is to know if plus or minus sign
for(int i=0;i<inputs.length;i++)
{
//notice we may encounter the case of -1-1, thus the leading minus sign should be ignored
if(inputs[i]== '+' || (inputs[i]=='-' && i!=0))// we differenciate here because we need know if plus or minus sign
{
opePosition = i;
ifPlusSign = inputs[i] == '+'?true:false;
break;
}
}
//after we identify the opePosition, we need find start/end of left and right operand
int leftOperandStart = 0;
int rightOperandEnd = opePosition+1;
//we need to deal with negative value cases
if(inputs[rightOperandEnd]=='-')
{
rightOperandEnd++;
}
while(rightOperandEnd<inputs.length && priority(inputs[rightOperandEnd])<1)
{
rightOperandEnd++;
}
int leftOperand = Integer.parseInt(exp.substring(0, opePosition));
int rightOperand = Integer.parseInt(exp.substring(opePosition+1, rightOperandEnd));
int innerResult = 0;
if(ifPlusSign)
{
innerResult = leftOperand+rightOperand;
}
else
{
innerResult = leftOperand - rightOperand;
}
return Calculate(""+ innerResult+ exp.substring(rightOperandEnd));
}
else if(highestPriority==2)
{
// */ remaining
/*if(operatorCount==1 && inputs[0]=='-'){
return Integer.parseInt(exp);
}*/
int opePosition = -1;
boolean ifMultiplySign = true;//this is to know if plus or minus sign
for(int i=0;i<inputs.length;i++)
{
if(inputs[i]== '*' || (inputs[i]=='/' && i!=0))
{
opePosition = i;
ifMultiplySign = inputs[i] == '+'?true:false;
break;
}
}
int leftOperandStart = opePosition-1;
while(leftOperandStart>=0 && priority(inputs[leftOperandStart])<1)
{
leftOperandStart--;
}
int rightOperandEnd = opePosition+1;
if(inputs[rightOperandEnd]=='-')
{
rightOperandEnd++;
}
while( rightOperandEnd<inputs.length && priority(inputs[rightOperandEnd])<1)
{
rightOperandEnd++;
}
int leftOperand = Integer.parseInt(exp.substring(leftOperandStart+1, opePosition));
int rightOperand = Integer.parseInt(exp.substring(opePosition+1, rightOperandEnd));
int innerResult = 0;
if(ifMultiplySign)innerResult = leftOperand * rightOperand;
else innerResult = leftOperand / rightOperand;
return Calculate(exp.substring(0, leftOperandStart+1)+innerResult+exp.substring(rightOperandEnd));
}
else
{
int parOpen = -1;
int parEnd = -1;
int parOpenEndiff = 0;
for(int i=0;i<inputs.length;i++)
{
if(inputs[i]=='(')
{
parOpen=parOpen<0?i:parOpen;
parOpenEndiff++;
}
else if(inputs[i]==')')
{
parOpenEndiff--;
if(parOpenEndiff==0)
{
parEnd = i;
break;
}
}
}
int innerResult = Calculate(exp.substring(parOpen+1,parEnd));
return Calculate(exp.substring(0, parOpen)+innerResult+exp.substring(parEnd+1));
}
}
}
How could I change my code to accept double value from the user ? (actually this program works fine with int values ).please could you help me to customize the program for double values also .....
String exp = input.next(); --> double exp = input.nextDouble();
Or:
String exp = input.next();
double value = Double.parseDouble(exp);
Do double value = Double.parseDouble(exp); in switch default case.

Categories

Resources