Last active
August 29, 2015 13:57
-
-
Save yangwansu/9679634 to your computer and use it in GitHub Desktop.
신용카드번호 검증 LUHN 알고리즘 TDD 로 구현
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.slipp.study.tdd.luhn; | |
import org.apache.commons.lang.ArrayUtils; | |
//LUHN | |
public class CardNumber { | |
private final Integer[] numbers; | |
private final Integer checksum; | |
private final String cardNumberString; | |
public CardNumber(String cardNumberString) { | |
this.cardNumberString = cardNumberString; | |
this.numbers = convertArray() ; | |
this.checksum = numbers[numbers.length - 1]; | |
} | |
Integer[] getTargets() { | |
Integer[] sub = (Integer[]) ArrayUtils.subarray(ArrayUtils.clone(numbers), 0, numbers.length-1); | |
ArrayUtils.reverse(sub); | |
return sub; | |
} | |
Integer[] convertArray() { | |
Integer[] array = new Integer[cardNumberString.length()]; | |
for(int i=0;i<cardNumberString.length();++i){ | |
array[i]=Integer.parseInt(cardNumberString.charAt(i)+""); | |
} | |
return array; | |
} | |
int checksum() { | |
return checksum; | |
} | |
int sumvalue() { | |
int sum=0; | |
Integer[] targets = getTargets(); | |
for(int i=0;i <targets.length;i++){ | |
int current = targets[i]; | |
if(0 == i%2){ | |
int doubles = (current*2); | |
//System.out.println(current+ "X2 = "+doubles+" : ("+ (doubles % 10) +" "+ (doubles / 10)+")"); | |
sum = sum + (doubles % 10) + (doubles / 10); | |
}else{ | |
//System.out.println(current); | |
sum = sum + current; | |
} | |
} | |
return sum; | |
} | |
static Integer nextTenNumber(int i) { | |
return 10*((i/10)+1); | |
} | |
Integer calculate() { | |
return nextTenNumber(sumvalue()) - sumvalue(); | |
} | |
public Boolean isValid() { | |
return checksum() == calculate(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.slipp.study.tdd.luhn; | |
import static org.hamcrest.CoreMatchers.is; | |
import static org.junit.Assert.assertThat; | |
import org.junit.Test; | |
public class LUHNTest { | |
/* | |
* | |
* 신용 카드상의 번호 검증을 위해 사용하는 알고리듬. 1960년대에 개발된 개방형 공식이다. | |
* 원리는 | |
* ㉠ 카드 번호의 우측 숫자부터 매 2번째 숫자마다 2를 곱하고, | |
* ㉡ 위 ㉠에서 2를 곱하지 않은 숫자들 중 가장 우측 수를 제외하고 (이 수는 추후 점검수로 쓰인다.) ㉠에서 나온 숫자들을 합한다 | |
* (㉠에서 나온 수가 2자리 수이면 2개의 숫자를 합한다). | |
* | |
* ㉢ 위 ㉡에서 나온 수와 그 다음으로 큰 10단위 수와의 차이를 구한다(㉡에서 나온 수가 34이면 다음으로 큰 10단위 수 40과의 차이, 6을 구한다). | |
* ㉢에서 나온 숫자가 카드의 점검 숫자와 일치해야 한다. | |
* | |
* */ | |
/* | |
카드번호 1234567890 은 유효하지 않은 카드 번호이다.(이하 넘버A ) | |
DONE 넘버A의 점검수(checksum)는 0 이다. | |
DONE 맨오른쪽수는_점검수이다. | |
DONE 넘버A의 ㄱ 계산값(sumvalue)는 43 이다. | |
DONE 넘버A의 ㄱ 계산값 의 다음 큰 10단위 수는 50 이다. | |
DONE 넘버A의 ㄷ 결과 값은 7 이다. | |
DONE CardNumber 생성자에 널 값 또는 빈 값 또는 숫자가 아닌 경우 | |
*/ | |
String 진짜신용카드번호 = "9436457659365131"; | |
String 잘못된카드번호 = "1234567890"; | |
@Test | |
public void 맨오른쪽수는_점검수이다() throws Exception{ | |
assertThat(new CardNumber(잘못된카드번호).checksum(), is(0)); | |
assertThat(new CardNumber("123456789").checksum(), is(9)); | |
assertThat(new CardNumber("12345678").checksum(), is(8)); | |
assertThat(new CardNumber(진짜신용카드번호).checksum(), is(1)); | |
} | |
@Test | |
public void sumvalue() throws Exception{ | |
assertThat(new CardNumber(잘못된카드번호).sumvalue(), is(43)); | |
assertThat(new CardNumber("0").sumvalue(), is(0)); | |
assertThat(new CardNumber("10").sumvalue(), is(2)); | |
assertThat(new CardNumber("210").sumvalue(), is(4)); | |
assertThat(new CardNumber("3210").sumvalue(), is(10)); | |
assertThat(new CardNumber(진짜신용카드번호).sumvalue(), is(79)); | |
} | |
@Test | |
public void getTargets() throws Exception{ | |
assertString(new CardNumber("0").getTargets(), ""); | |
assertString(new CardNumber("90").getTargets(), "9"); | |
assertString(new CardNumber("890").getTargets(), "98"); | |
assertString(new CardNumber(잘못된카드번호).getTargets(), "987654321"); | |
} | |
private void assertString(Integer[] actual, String expected) { | |
String ret = ""; | |
for (Integer each : actual) { | |
ret=ret+each; | |
} | |
assertThat(ret,is(expected)); | |
} | |
@Test | |
public void 다음10단위구하기() throws Exception{ | |
assertThat(CardNumber.nextTenNumber(0),is(10)); | |
assertThat(CardNumber.nextTenNumber(1),is(10)); | |
assertThat(CardNumber.nextTenNumber(9),is(10)); | |
assertThat(CardNumber.nextTenNumber(10),is(20)); | |
assertThat(CardNumber.nextTenNumber(11),is(20)); | |
assertThat(CardNumber.nextTenNumber(19),is(20)); | |
assertThat(CardNumber.nextTenNumber(20),is(30)); | |
assertThat(CardNumber.nextTenNumber(43),is(50)); | |
} | |
@Test | |
public void 최종결과() throws Exception{ | |
assertThat(new CardNumber(잘못된카드번호).calculate(), is(7)); | |
assertThat(new CardNumber(진짜신용카드번호).calculate(), is(1)); | |
} | |
@Test | |
public void 유효체크() throws Exception{ | |
assertThat(new CardNumber(잘못된카드번호).isValid(), is(false)); | |
assertThat(new CardNumber(진짜신용카드번호).isValid(), is(true)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
LUHN 알고리즘
http://www.thetaoofmakingmoney.com/2007/04/12/324.html