Aro*_*rom 5 java loops if-statement
我是计算机科学入门课程的高中生.我们的任务如下:
信用卡号码的最后一位是校验位,可防止转录错误,例如单个数字错误或切换两位数字.以下方法用于验证实际的信用卡号,但为简单起见,我们将为8位数而不是16位的数字描述它:
编写实现此算法的程序.用户应提供一个8位数字,您应该打印出该号码是否有效.如果它无效,您应该打印出使数字有效的校验位的值.
我做了一切,除了粗体部分.我的代码如下:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
循环是我遇到的问题.无论何时编译,我总是以无限循环结束.但看起来一切都应该有效.它应该减少校验数字的值(不增加,所以我不会以10或更高的校验位数结束),然后将该数字添加回总和,直到总和可以被10整除,并且然后循环结束.循环的类型我使用错了吗?任何意见,将不胜感激.
你的问题是你的两个循环条件都涉及totalSum但你只改变了checkDigit。
while (totalSum % 10 != 0)
{
checkDigit--;
if (totalSum % 10 == 0)
{
break;
}
}
Run Code Online (Sandbox Code Playgroud)
您需要重新计算totalSum或更改基于 的条件checkDigit。如果您想像现在一样循环和递减,您将需要添加一个执行算法并每次调用它的方法。您概述类的方式使这非常不方便,因为您不转换数字。
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;
}
Run Code Online (Sandbox Code Playgroud)
现在你可以做类似的事情:
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];
}
Run Code Online (Sandbox Code Playgroud)
但您应该能够仅减去差异即可找到有效的校验位:
if (totalSum % 10 != 0) checkDigit -= totalSum % 10;
Run Code Online (Sandbox Code Playgroud)
或者类似的东西:
public void makeItValid() {
int[] invalidNumbers = cardToNumbers(creditCardNumber);
checkDigit = invalidNumbers[invalidNumbers.length - 1] -= totalSum % 10;
totalSum = calcTotalSum(invalidNumbers);
valid = true;
}
Run Code Online (Sandbox Code Playgroud)
一些旁白,
我建议将数字存储为字段并checkDigit表示数组中的索引。这将简化您正在执行的一些操作。
我还建议不要像在您的makeItValid方法中那样“默默地”更改 IE 内部的字段,除非这是作业的规范。我认为更好的形式是让“拥有”代码本身进行更改,这在外部更清晰。一个比较完整的实现看起来像这样:
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
}
Run Code Online (Sandbox Code Playgroud)
IMO 的最佳形式是根本不允许创建信用卡对象,除非校验位有效。作为 OOP 原则,创建无效信用卡是没有意义的。如果卡无效,构造函数应该抛出异常,并且有一个静态方法来更正号码。
我会做类似以下的事情(缩短):
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);
}
Run Code Online (Sandbox Code Playgroud)
我想这或多或少是在为你做功课,但我相信你可以从中学习。
| 归档时间: |
|
| 查看次数: |
2833 次 |
| 最近记录: |