Luhn test of credit card numbers: Difference between revisions

m
 
(18 intermediate revisions by 12 users not shown)
Line 1,345:
end if
next test</syntaxhighlight>
 
==={{header|Chipmunk Basic}}===
{{works with|Chipmunk Basic|3.6.4}}
<syntaxhighlight lang="qbasic">100 cls
110 rem Luhn test
120 dim card$(5)
130 card$(1) = "49927398716"
140 card$(2) = "49927398717"
150 card$(3) = "1234567812345678"
160 card$(4) = "1234567812345670"
170 for test = 1 to 4
180 odd = true
190 sum = 0
200 for n = len(card$(test)) to 1 step -1
210 num = val(mid$(card$(test),n,1))
220 if odd then
230 sum = sum+num
240 odd = false
250 else
260 num = num*2
270 if num <= 9 then
280 sum = sum+num
290 else
300 sum = sum+val(left$(str$(num),1))+val(right$(str$(num),1))
310 endif
320 odd = true
330 endif
340 next
350 if sum mod 10 = 0 then
360 print card$(test),"True"
370 else
380 print card$(test),"False"
390 endif
400 next test</syntaxhighlight>
 
==={{header|IS-BASIC}}===
<syntaxhighlight lang="is-basic">100 PROGRAM "CredCard.bas"
110 DO
120 PRINT :PRINT "Credit card number:":INPUT PROMPT ">":CCN$
130 IF CCN$="" THEN EXIT DO
140 IF LUHN(TRIM$(CCN$)) THEN
150 PRINT "Card number is valid."
160 ELSE
170 SET #102:INK 3:PRINT "Card number is invalid.":SET #102:INK 1
180 END IF
190 LOOP
200 DEF LUHN(CCN$)
210 LET L=LEN(CCN$):LET S=0
220 FOR I=1 TO L
230 LET N=VAL(CCN$(L-I+1))
240 IF I BAND 1 THEN
250 LET S=S+N
260 ELSE
270 LET N=N*2:LET S=S+MOD(N,10)+INT(N/10)
280 END IF
290 NEXT
300 LET LUHN=MOD(S,10)=0
310 END DEF
320 DEF TRIM$(S$)
330 LET T$=""
340 FOR I=1 TO LEN(S$)
350 IF S$(I)>CHR$(47) AND S$(I)<CHR$(58) THEN LET T$=T$&S$(I)
360 NEXT
370 LET TRIM$=T$
380 END DEF</syntaxhighlight>
 
Output:
<pre>Credit card number:
>49927398716
Card number is valid.
 
Credit card number:
>49927398717
Card number is invalid.
 
Credit card number:
>1234 5678 1234 5678
Card number is invalid.
 
Credit card number:
>1234 5678 1234 5670
Card number is valid.</pre>
 
==={{header|QBasic}}===
Line 1,413 ⟶ 1,495:
NEXT test
END</syntaxhighlight>
 
==={{header|uBasic/4tH}}===
{{Trans|C}}
<syntaxhighlight lang="qbasic">Print " 49927398716", Show (Iif(FUNC(_Luhn ("49927398716")), "ok", "fail"))
Print " 49927398717", Show (Iif(FUNC(_Luhn ("49927398717")), "ok", "fail"))
Print "1234567812345678", Show (Iif(FUNC(_Luhn ("1234567812345678")), "ok", "fail"))
Print "1234567812345670", Show (Iif(FUNC(_Luhn ("1234567812345670")), "ok", "fail"))
End
 
_Luhn
Param (1)
Local (4)
 
c@ = 1 : d@ = 0
 
For b@ = Len(a@)-1 To 0 Step -1
e@ = Peek(a@, b@) - Ord("0")
d@ = d@ + Iif (c@, e@, e@+e@-9*(e@>4))
c@ = c@ = 0
Next
 
Return ((d@ % 10) = 0)
</syntaxhighlight>
{{Out}}
<pre> 49927398716 ok
49927398717 fail
1234567812345678 fail
1234567812345670 ok
 
0 OK, 0:333</pre>
 
==={{header|Yabasic}}===
Line 1,445 ⟶ 1,557:
fi
next test</syntaxhighlight>
 
 
=={{header|Batch File}}==
Line 1,716 ⟶ 1,827:
$ echo 1234567812345670 | beef luhn.bf
Pass</pre>
 
=={{header|Bruijn}}==
<syntaxhighlight lang="bruijn">
:import std/Combinator .
:import std/Math .
:import std/List .
 
luhn number→list → reverse → check → (\mod (+10)) → zero?
check y [[[[0 [[[6 \5 (4 + (5 odd even)) 1]]] 1]]]] k (+0)
odd 2
even digit-sum (2 ⋅ (+2))
 
:test (luhn (+61789372994)) ([[1]])
:test (luhn (+49927398716)) ([[1]])
:test (luhn (+49927398717)) ([[0]])
:test (luhn (+1234567812345678)) ([[0]])
:test (luhn (+1234567812345670)) ([[1]])
</syntaxhighlight>
 
=={{header|Burlesque}}==
Line 2,630 ⟶ 2,759:
writefln("%s is %svalid", n, luhnTest(n) ? "" : "not ");
}</syntaxhighlight>
 
=={{header|Delphi}}==
{{works with|Delphi|6.0}}
{{libheader|SysUtils,StdCtrls}}
Uses an array to handle the situation where multiply a term by 2, creates a two digit number. The array automatically handles adding each digit of the resulting two digit number. Also, avoids reversing the number by traversing the array backwards
 
<syntaxhighlight lang="Delphi">
{Test data arrays}
 
const Num1: array [0..10] of byte = (4,9,9,2,7,3,9,8,7,1,6);
const Num2: array [0..10] of byte = (4,9,9,2,7,3,9,8,7,1,7);
const Num3: array [0..15] of byte = (1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8);
const Num4: array [0..15] of byte = (1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,0);
 
{Simplifies cases where we have to sum a two digit number}
 
const DigitSum: array [0..18] of byte = (0,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9);
 
function ValidateCreditCard(CardNum: array of byte): boolean;
{Validate a Credit Card number}
var I,J,Len,Sum,Sum1,Sum2: integer;
var Rev: array of byte;
begin
Sum1:=0; Sum2:=0;
Len:=High(CardNum);
for I:=Len downto 0 do
if ((I-Len) and 1)=0 then Sum1:=Sum1 + CardNum[I]
else Sum2:=Sum2 + DigitSum[CardNum[I]*2];
Sum:=Sum1+Sum2;
Result:=(Sum mod 10)=0;
end;
 
 
function CardNumberToStr(CardNum: array of byte): string;
{Convert card number to a string}
var I: integer;
begin
Result:='';
for I:=0 to High(CardNum) do
Result:=Result+IntToStr(CardNum[I]);
end;
 
 
procedure TestDisplayNumber(Memo: TMemo; Num: array of byte);
{Test a credit card number and display results}
var S: string;
begin
S:=CardNumberToStr(Num);
if ValidateCreditCard(Num) then S:=S+': Valid'
else S:=S+': Not Valid';
Memo.Lines.Add(S);
end;
 
 
procedure TestCreditCardNums(Memo: TMemo);
{Test all credit card numbers}
begin
TestDisplayNumber(Memo,Num1);
TestDisplayNumber(Memo,Num2);
TestDisplayNumber(Memo,Num3);
TestDisplayNumber(Memo,Num4);
end;
 
 
</syntaxhighlight>
{{out}}
<pre>
49927398716: Valid
49927398717: Not Valid
1234567812345678: Not Valid
1234567812345670: Valid
 
</pre>
 
 
=={{header|Draco}}==
Line 2,670 ⟶ 2,873:
1234567812345678: fail
1234567812345670: pass</pre>
 
=={{header|EasyLang}}==
<syntaxhighlight>
func luhn cc$ .
for i = len cc$ downto 1
odd = 1 - odd
dig = number substr cc$ i 1
if odd = 0
dig = 2 * dig
if dig >= 10
dig -= 9
.
.
sum += dig
.
return if sum mod 10 = 0
.
cc$[] = [ "49927398716" "49927398717" "1234567812345678" "1234567812345670" ]
for cc$ in cc$[]
write cc$ & " "
if luhn cc$ = 1
print "is valid"
else
print "is not valid"
.
.
</syntaxhighlight>
{{out}}
<pre>
49927398716 is valid
49927398717 is not valid
1234567812345678 is not valid
1234567812345670 is valid
</pre>
 
=={{header|EchoLisp}}==
Line 3,419 ⟶ 3,656:
1234567812345670 - valid
</pre>
 
=={{header|IS-BASIC}}==
<syntaxhighlight lang="is-basic">100 PROGRAM "CredCard.bas"
110 DO
120 PRINT :PRINT "Credit card number:":INPUT PROMPT ">":CCN$
130 IF CCN$="" THEN EXIT DO
140 IF LUHN(TRIM$(CCN$)) THEN
150 PRINT "Card number is valid."
160 ELSE
170 SET #102:INK 3:PRINT "Card number is invalid.":SET #102:INK 1
180 END IF
190 LOOP
200 DEF LUHN(CCN$)
210 LET L=LEN(CCN$):LET S=0
220 FOR I=1 TO L
230 LET N=VAL(CCN$(L-I+1))
240 IF I BAND 1 THEN
250 LET S=S+N
260 ELSE
270 LET N=N*2:LET S=S+MOD(N,10)+INT(N/10)
280 END IF
290 NEXT
300 LET LUHN=MOD(S,10)=0
310 END DEF
320 DEF TRIM$(S$)
330 LET T$=""
340 FOR I=1 TO LEN(S$)
350 IF S$(I)>CHR$(47) AND S$(I)<CHR$(58) THEN LET T$=T$&S$(I)
360 NEXT
370 LET TRIM$=T$
380 END DEF</syntaxhighlight>
 
Output:
<pre>Credit card number:
>49927398716
Card number is valid.
 
Credit card number:
>49927398717
Card number is invalid.
 
Credit card number:
>1234 5678 1234 5678
Card number is invalid.
 
Credit card number:
>1234 5678 1234 5670
Card number is valid.</pre>
 
=={{header|J}}==
Line 3,733 ⟶ 3,922:
=={{header|langur}}==
{{trans|Go}}
<syntaxhighlight lang="langur">val .luhntest = fn(.s) {
{{works with|langur|0.8.10}}
<syntaxhighlight lang="langur">val .luhntest = f(.s) {
val .t = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]
val .numbers = s2n .s
Line 3,744 ⟶ 3,932:
}
 
val .tests = h{
"49927398716": true,
"49927398717": false,
Line 3,958 ⟶ 4,146:
1234567812345678 = False
1234567812345670 = True</pre>
 
=={{header|MACRO-11}}==
<syntaxhighlight lang="macro11"> .TITLE LUHN
.MCALL .GTLIN,.PRINT,.EXIT
LUHN:: .GTLIN #5$
MOV #5$,R0
TSTB (R0)
BEQ 2$
JSR PC,TEST
BNE 1$
.PRINT #3$
BR LUHN
1$: .PRINT #4$
BR LUHN
2$: .EXIT
3$: .ASCIZ /PASS/
4$: .ASCIZ /FAIL/
5$: .BLKB 200
.EVEN
TEST: MOV R0,R1
CLR R2
1$: TSTB (R0)+
BNE 1$
DEC R0
2$: MOVB -(R0),R3
SUB #60,R3
ADD R3,R2
CMP R0,R1
BLOS 3$
MOVB -(R0),R3
SUB #60,R3
MOVB 4$(R3),R3
ADD R3,R2
CMP R0,R1
BHI 2$
3$: SUB #12,R2
BHI 3$
RTS PC
4$: .BYTE ^D0,^D2,^D4,^D6,^D8
.BYTE ^D1,^D3,^D5,^D7,^D9
.END LUHN</syntaxhighlight>
{{out}}
<pre>.LUHN 49927398716
PASS
 
.LUHN 49927398717
FAIL
 
.LUHN 1234567812345678
FAIL
 
.LUHN 1234567812345670
PASS</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
Line 5,283 ⟶ 5,525:
ok 4 - 1234567812345670 passes the Luhn test.</pre>
 
=={{header|Refal}}==
<syntaxhighlight lang="refal">$ENTRY Go {
= <Test '49927398716'>
<Test '49927398717'>
<Test '1234567812345678'>
<Test '1234567812345670'>;
};
 
Test {
e.Digits = <Prout e.Digits ': ' <Luhn e.Digits>>;
};
 
Luhn {
(s.Sum) e.Digits s.Even s.Odd,
<Mul 2 <Numb s.Even>>: s.Even2,
<Divmod s.Even2 10>: (s.EvenD1) s.EvenD2,
<+ s.EvenD1 s.EvenD2>: s.EvenV,
<+ <Numb s.Odd> s.EvenV>: s.Step
= <Luhn (<+ s.Sum s.Step>) e.Digits>;
(s.Sum) s.Odd = <Luhn (<+ s.Sum <Numb s.Odd>>)>;
(s.Sum), <Divmod s.Sum 10>: (s.Rest) s.Last,
s.Last: {
0 = Valid;
s.X = Invalid;
};
e.Digits = <Luhn (0) e.Digits>;
};</syntaxhighlight>
{{out}}
<pre>49927398716: Valid
49927398717: Invalid
1234567812345678: Invalid
1234567812345670: Valid</pre>
=={{header|REXX}}==
===version 1===
Line 5,420 ⟶ 5,694:
1234567812345678 -> Invalid
1234567812345670 -> Valid
</pre>
 
=={{header|RPL}}==
Card numbers shall be entered as strings to avoid any rounding error when testing long ones.
{{works with|RPL|HP48-C}}
{| class="wikitable"
! RPL code
! Comment
|-
|
« 0 → card even
« 0
card SIZE 1 '''FOR''' j
card j DUP SUB OBJ→
'''IF''' even '''THEN'''
DUP + 10 MOD LASTARG / IP + '''END'''
+ 1 'even' STO-
-1 '''STEP'''
10 MOD NOT
» » '<span style="color:blue">LUHN?</span>' STO
|
<span style="color:blue">LUHN?</span> ''( "card_number" -- boolean ) ''
sum = 0
loop for j=n to 1
digit = card[j]
if even digit
multiply it by 2 and add digits
sum += digit ; reverse parity flag
return not(sum mod 10)
|}
{ "49927398716" "49927398717" "1234567812345678" "1234567812345670" } 1 « <span style="color:blue">LUHN?</span> » DOLIST
{{out}}
<pre>
1: { 1 0 0 1 }
</pre>
 
Line 5,812 ⟶ 6,122:
1234567812345678: FAIL
1234567812345670: OK</pre>
 
=={{header|SparForte}}==
As a structured script.
<syntaxhighlight lang="ada">#!/usr/local/bin/spar
pragma annotate( summary, "luhn test of credit card numbers" )
@( description, "The Luhn test is used by some credit card companies to " )
@( description, "distinguish valid credit card numbers from what could be a random selection of digits." )
@( see_also, "https://rosettacode.org/wiki/Luhn_test_of_credit_card_number" )
@( author, "Ken O. Burtch" );
pragma license( unrestricted );
 
pragma restriction( no_external_commands );
 
procedure luhn is
 
bad_digit : exception;
 
-- return true if the card number passes the luhn test
 
function is_luhn( card_number : string) return boolean is
card_num_len : constant natural := strings.length( card_number );
checksum: natural := 0;
ch : character;
begin
for i in reverse 1..card_num_len loop
ch := strings.element( card_number, i );
if strings.is_digit( ch ) then
declare
ord : constant natural := numerics.pos(ch);
begin
if ((card_num_len-1) and (i-1) ) /= 0 then
checksum := @ + ord;
else
checksum := @ + numerics.floor(ord / 5) + ((2*ord) mod 10);
end if;
end;
else
raise bad_digit;
end if;
end loop;
return checksum mod 10 = 0;
end is_luhn;
 
-- check a credit card and display the result
 
procedure check_card( card_number : string ) is
begin
put( card_number )
@( ": " )
@( is_luhn( card_number ) );
new_line;
end check_card;
 
begin
check_card("49927398716");
check_card("49927398717");
check_card("1234567812345678");
check_card("1234567812345670");
end luhn;</syntaxhighlight>
 
=={{header|SPARK}}==
Line 6,428 ⟶ 6,797:
</pre>
 
=={{header|V (Vlang)}}==
{{trans|go}}
<syntaxhighlight lang="v (vlang)">const (
input = '49927398716
49927398717
Line 6,470 ⟶ 6,839:
=={{header|Wren}}==
{{libheader|Wren-fmt}}
{{libheader|Wren-traititerate}}
<syntaxhighlight lang="ecmascriptwren">import "./fmt" for Fmt
import "./traititerate" for Stepped
 
var luhn = Fn.new { |s|
Line 6,491 ⟶ 6,860:
for (test in tests) {
var ans = (luhn.call(test)) ? "pass" : "fail"
SystemFmt.print("%(Fmt.$-16s -> $s(-16", test)), -> %(ans)")
}</syntaxhighlight>
 
885

edits