IBAN: Difference between revisions

83,261 bytes added ,  6 months ago
m
No edit summary
m (→‎{{header|Wren}}: Minor tidy)
 
(62 intermediate revisions by 34 users not shown)
Line 1:
{{task|Checksums}}
{{wikipedia}}
 
The [[wp:International_Bank_Account_Number|International Bank Account Number (IBAN)]] is an internationally agreed means of identifying bank accounts across national borders with a reduced risk of propagating [[wp:Transcription_error|transcription errors]]. <br>
 
The IBAN consists of up to 34 alphanumeric characters: first the two-letter ISO 3166-1 alpha-2 country code, then two check digits, and finally a country-specific Basic Bank Account Number (BBAN). <br>
The &nbsp; [[wp:International_Bank_Account_Number|International Bank Account Number (IBAN)]] &nbsp; is an internationally agreed means of identifying bank accounts across national borders with a reduced risk of propagating [[wp:Transcription_error|transcription errors]].
 
The IBAN consists of up to '''34''' alphanumeric characters:
::* &nbsp; first the two-letter ISO 3166-1 alpha-2 country code,
::* &nbsp; then two check digits, and
::* &nbsp; finally a country-specific Basic Bank Account Number (BBAN).
 
 
The check digits enable a sanity check of the bank account number to confirm its integrity even before submitting a transaction.
 
 
The task here is to validate the following fictitious IBAN: <tt>GB82 WEST 1234 5698 7654 32</tt>.
;Task:
Validate the following fictitious IBAN: &nbsp; <tt> GB82 WEST 1234 5698 7654 32 </tt>
 
 
Details of the algorithm can be found on the Wikipedia page.
<br><br>
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">F mod97(numberstring)
V segstart = 0
V step = 9
V prepended = ‘’
V number = 0
L segstart < numberstring.len - step
number = Int(prepended‘’numberstring[segstart .< segstart + step])
V remainder = number % 97
prepended = String(remainder)
I remainder < 10
prepended = ‘0’prepended
segstart += step
step = 7
number = Int(prepended‘’numberstring[segstart ..])
R number % 97
 
V country2length = [‘IS’ = 26, ‘IT’ = 27, ‘MT’ = 31, ‘MU’ = 30, ‘MR’ = 27, ‘MK’ = 19, ‘IE’ = 22, ‘MD’ = 24,
‘ME’ = 22, ‘MC’ = 27, ‘IL’ = 23, ‘DE’ = 22, ‘DO’ = 28, ‘DK’ = 18, ‘PK’ = 24, ‘HR’ = 21,
‘HU’ = 28, ‘FI’ = 18, ‘LU’ = 20, ‘LT’ = 20, ‘LV’ = 21, ‘KW’ = 30, ‘LI’ = 21, ‘PS’ = 29,
‘PT’ = 25, ‘LB’ = 28, ‘GB’ = 22, ‘GE’ = 22, ‘CR’ = 21, ‘TR’ = 26, ‘GI’ = 23, ‘GL’ = 18,
‘CY’ = 28, ‘CZ’ = 24, ‘GR’ = 27, ‘GT’ = 28, ‘KZ’ = 20, ‘TN’ = 24, ‘CH’ = 21, ‘SE’ = 24,
‘SA’ = 24, ‘SM’ = 27, ‘SI’ = 19, ‘SK’ = 24, ‘PL’ = 28, ‘BR’ = 29, ‘FR’ = 27, ‘FO’ = 18,
‘BA’ = 20, ‘BG’ = 22, ‘BE’ = 16, ‘BH’ = 22, ‘VG’ = 24, ‘RO’ = 24, ‘RS’ = 22, ‘NO’ = 15,
‘NL’ = 18, ‘AZ’ = 28, ‘EE’ = 20, ‘AT’ = 20, ‘ES’ = 24, ‘AL’ = 28, ‘AD’ = 24, ‘AE’ = 23]
 
F valid_iban(iban_)
V iban = iban_.replace(‘ ’, ‘’).replace("\t", ‘’)
I !re:‘[\dA-Z]+’.match(iban)
R 0B
 
I iban.len != :country2length[iban[0.<2]]
R 0B
 
iban = iban[4..]‘’iban[0.<4]
R mod97(iban.map(ch -> String(Int(ch, radix' 36))).join(‘’)) == 1
 
L(account) [‘GB82 WEST 1234 5698 7654 32’,
‘GB82 TEST 1234 5698 7654 32’]
print(‘#. validation is: #.’.format(account, valid_iban(account)))</syntaxhighlight>
 
{{out}}
<pre>
GB82 WEST 1234 5698 7654 32 validation is: 1B
GB82 TEST 1234 5698 7654 32 validation is: 0B
</pre>
 
=={{header|Ada}}==
<langsyntaxhighlight Adalang="ada">package Iban_Code is
function Is_Legal(Iban : String) return Boolean;
end Iban_Code;</langsyntaxhighlight><syntaxhighlight lang Ada="ada">with Ada.Characters.Handling; use Ada.Characters.Handling;
with Ada.Containers.Hashed_Maps;
with Ada.Strings.Hash;
Line 99 ⟶ 160:
Nations.insert("TR", 26); Nations.insert("AE", 23);
Nations.insert("GB", 22); Nations.insert("VG", 24);
end Iban_Code;</langsyntaxhighlight>Testing:
<langsyntaxhighlight Adalang="ada">with Ada.Text_Io; use Ada.Text_Io;
with Iban_Code;
 
Line 120 ⟶ 181:
Check("GB82 TEST 1234 5698 7654 32");
Check("GB82 WEST 1243 5698 7654 32");
end Check_Iban;</langsyntaxhighlight>{{out}}
GB82 WEST 1234 5698 7654 32 is valid.
GB82WEST12345698765432 is valid.
Line 126 ⟶ 187:
GB82 TEST 1234 5698 7654 32 is not valid.
GB82 WEST 1243 5698 7654 32 is not valid.
 
=={{header|AppleScript}}==
 
<syntaxhighlight lang="applescript">on countryCodes()
-- A list of 34 lists. The nth list (1-indexed) contains country codes for countries having n-character IBANS.
return {{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {"NO"}, {"BE"}, ¬
{}, {"DK", "FO", "FI", "GL", "NL"}, {"MK", "SI"}, {"AT", "BA", "EE", "KZ", "XK", "LT", "LU"}, ¬
{"HR", "LV", "LI", "CH"}, {"BH", "BG", "CR", "GE", "DE", "IE", "ME", "RS", "GB", "VA"}, ¬
{"TL", "GI", "IQ", "IL", "AE"}, {"AD", "CZ", "MD", "PK", "RO", "SA", "SK", "ES", "SE", "TN", "VG"}, ¬
{"PT", "ST"}, {"IS", "TR"}, {"FR", "GR", "IT", "MR", "MC", "SM"}, ¬
{"AL", "AZ", "BY", "CY", "DO", "SV", "GT", "HU", "LB", "PL"}, {"BR", "EG", "PS", "QA", "UA"}, ¬
{"JO", "KW", "MU"}, {"MT", "SC"}, {"LC"}, {}, {}}
end countryCodes
 
on validateIBAN(iban)
-- Remove any spaces.
if (iban contains space) then set iban to replaceText(iban, space, "")
considering diacriticals but ignoring case
-- Check the length both overall and against the presumed country code.
set characterCount to (count iban)
if ((characterCount > 34) or (text 1 thru 2 of iban is not in item characterCount of countryCodes())) then return false
-- Move the first four characters to the end.
set iban to text 5 thru -1 of iban & (text 1 thru 4 of iban)
-- Replace any unadorned Latin letters with the appropriate number characters ("A" = "11" … "Z" = "35").
repeat with letter in "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
if (iban contains letter) then set iban to replaceText(iban, letter, ((letter's id) mod 32 + 9) as text)
end repeat
end considering
-- Check that what's left only contains digit characters.
if (replaceText(iban, characters of "0123456789", "") is not "") then return false
-- Calculate the mod-97 remainder.
set characterCount to (count iban)
set c to (characterCount - 1) mod 7 + 1
set mod97 to (text 1 thru c of iban) mod 97
repeat with c from (c + 1) to characterCount by 7
set mod97 to (mod97 * 10000000 + (text c thru (c + 6) of iban)) mod 97
end repeat
return (mod97 = 1)
end validateIBAN
 
on replaceText(txt, searchStr, replaceText)
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to searchStr
set txt to txt's text items
set AppleScript's text item delimiters to replaceText
set txt to txt as text
set AppleScript's text item delimiters to astid
return txt
end replaceText
 
-- Test code (IBANs borrowed from other solutions on this page.):
local testIBANs, output, thisIBAN, astid
 
set testIBANs to {"GB82 WEST 1234 5698 7654 32", "gb82 west 1234 5698 7654 32", "GB82 TEST 1234 5698 7654 32", ¬
"SA03 8000 0000 6080 1016 7519", "ZZ12 3456 7890 1234 5678 12", "IL62 0108 0000 0009 9999 999"}
set output to {}
repeat with thisIBAN in testIBANs
set end of output to thisIBAN & item ((validateIBAN(thisIBAN) as integer) + 1) of {": invalid", ": valid"}
end repeat
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to linefeed
set output to output as text
set AppleScript's text item delimiters to astid
return output</syntaxhighlight>
 
{{output}}
<syntaxhighlight lang="applescript">"GB82 WEST 1234 5698 7654 32: valid
gb82 west 1234 5698 7654 32: valid
GB82 TEST 1234 5698 7654 32: invalid
SA03 8000 0000 6080 1016 7519: valid
ZZ12 3456 7890 1234 5678 12: invalid
IL62 0108 0000 0009 9999 999: valid"</syntaxhighlight>
 
=={{header|Arturo}}==
 
<syntaxhighlight lang="rebol">ibanSize: #[
AL: 28, AD: 24, AT: 20, AZ: 28, BE: 16
BH: 22, BA: 20, BR: 29, BG: 22, CR: 21, HR: 21, CY: 28
CZ: 24, DK: 18, DO: 28, EE: 20, FO: 18, FI: 18, FR: 27
GE: 22, DE: 22, GI: 23, GR: 27, GL: 18, GT: 28, HU: 28
IS: 26, IE: 22, IL: 23, IT: 27, KZ: 20, KW: 30, LV: 21
LB: 28, LI: 21, LT: 20, LU: 20, MK: 19, MT: 31, MR: 27
MU: 30, MC: 27, MD: 24, ME: 22, NL: 18, NO: 15, PK: 24
PS: 29, PL: 28, PT: 25, RO: 24, SM: 27, SA: 24, RS: 22
SK: 24, SI: 19, ES: 24, SE: 24, CH: 21, TN: 24, TR: 26
AE: 23, GB: 22, VG: 24
]
base36: (map 0..9 'x -> to :string x) ++
map 97..122 'x -> upper to :string to :char x
valid?: function [iban][
iban: replace iban " " ""
if not? contains? iban {/[0-9A-Z]+/} -> return false
if not? (size iban)=ibanSize\[slice iban 0 1] -> return false
 
iban: (slice iban 4 (size iban)-1) ++ slice iban 0 3
iban: join map split iban 'ch -> to :string index base36 ch
iban: to :integer iban
 
return 1=iban%97
]
loop ["GB82 WEST 1234 5698 7654 32"
"GB82 TEST 1234 5698 7654 32"] 'ib
-> print [ib "=> valid?" valid? ib]</syntaxhighlight>
 
{{out}}
 
<pre>GB82 WEST 1234 5698 7654 32 => valid? true
GB82 TEST 1234 5698 7654 32 => valid? false</pre>
 
=={{header|AutoHotkey}}==
{{works with|AutoHotkey 1.1}}
<langsyntaxhighlight AutoHotkeylang="autohotkey">IBANs := ["GB82 WEST 1234 5698 7654 32"
, "gb82 WEST 1234 5698 7654 32"
, "GB82WEST12345698765432"
Line 171 ⟶ 344:
}
return rem
}</langsyntaxhighlight>{{Out}}
GB82 WEST 1234 5698 7654 32 is valid.
gb82 WEST 1234 5698 7654 32 is valid.
Line 178 ⟶ 351:
GB82 WEST 1234 5698 7654 33 is not valid.
AE82 WEST 1234 5698 7654 32 is not valid.
 
=={{header|AWK}}==
{{works with|gawk}}
 
This requires a gawk with extensions and GNU MP+MPFR support - it's usually the case. Some country codes are missing, the output is itself parsable.
 
<syntaxhighlight lang="awk">
@load "ordchr"
 
function invalid() { print("INVALID " $0); next }
function valid() { print("VALID__ " $0) }
 
BEGIN {
ccibanlen["AL"] = 28; ccibanlen["AD"] = 24; ccibanlen["AT"] = 20;
ccibanlen["AZ"] = 28; ccibanlen["BH"] = 22; ccibanlen["BA"] = 20;
ccibanlen["BR"] = 29; ccibanlen["BG"] = 22; ccibanlen["CR"] = 21;
ccibanlen["HR"] = 21; ccibanlen["CY"] = 28; ccibanlen["CZ"] = 24;
ccibanlen["DK"] = 18; ccibanlen["DO"] = 28; ccibanlen["EE"] = 20;
ccibanlen["FO"] = 18; ccibanlen["FI"] = 18; ccibanlen["FR"] = 27;
ccibanlen["GE"] = 22; ccibanlen["DE"] = 22; ccibanlen["GI"] = 23;
ccibanlen["GR"] = 27; ccibanlen["GL"] = 18; ccibanlen["GT"] = 28;
ccibanlen["HU"] = 28; ccibanlen["IS"] = 26; ccibanlen["IE"] = 22;
ccibanlen["IT"] = 27; ccibanlen["KZ"] = 20; ccibanlen["KW"] = 30;
ccibanlen["LV"] = 21; ccibanlen["LB"] = 28; ccibanlen["LI"] = 21;
ccibanlen["LT"] = 20; ccibanlen["LU"] = 20; ccibanlen["MK"] = 19;
ccibanlen["MT"] = 31; ccibanlen["MR"] = 27; ccibanlen["MU"] = 30;
ccibanlen["MC"] = 27; ccibanlen["MD"] = 24; ccibanlen["ME"] = 22;
ccibanlen["NL"] = 18; ccibanlen["NO"] = 15; ccibanlen["PK"] = 24;
ccibanlen["PS"] = 29; ccibanlen["PL"] = 28; ccibanlen["PT"] = 25;
ccibanlen["RO"] = 24; ccibanlen["SM"] = 27; ccibanlen["SA"] = 24;
ccibanlen["RS"] = 22; ccibanlen["SK"] = 24; ccibanlen["SI"] = 19;
ccibanlen["ES"] = 24; ccibanlen["SE"] = 24; ccibanlen["CH"] = 21;
ccibanlen["TN"] = 24; ccibanlen["TR"] = 26; ccibanlen["AE"] = 23;
ccibanlen["GB"] = 22; ccibanlen["VG"] = 24; ccibanlen["BE"] = 16;
}
 
{
iban = toupper($0)
gsub(/\s+/, "", iban)
ccode = substr(iban, 1, 2)
if ( ! match(iban, /^[A-Z0-9]+$/) ||
! (ccode in ccibanlen) ||
length(iban) != ccibanlen[ccode])
invalid()
ibanrev = gensub(/^(.{4})(.+)/, "\\2\\1", 1, iban)
ibancsum = ""
for (i = 1; i <= length(ibanrev); i++) {
currchar = substr(ibanrev, i, 1)
if (match(currchar, /[A-Z]/))
currchar = ord(currchar) - 55
ibancsum = ibancsum currchar
}
ibancsum % 97 == 1 ? valid() : invalid()
}</syntaxhighlight>
Creating a test file and launching the script:
<syntaxhighlight lang="text">
cat > test.iban
FR33 ^__^ 0BAD
AA11 1234 6543 1212
FR33 1234 5432
CH93 0076 2011 6238 5295 7
GB82 WEST 1234 5698 7654 32
GB82 TEST 1234 5698 7654 32
^D
gawk -Mf iban.gawk test.iban
</syntaxhighlight>
 
Output:
 
<syntaxhighlight lang="text">
INVALID FR33 ^__^ 0BAD
INVALID AA11 1234 6543 1212
INVALID FR33 1234 5432
VALID__ CH93 0076 2011 6238 5295 7
VALID__ GB82 WEST 1234 5698 7654 32
INVALID GB82 TEST 1234 5698 7654 32
</syntaxhighlight>
 
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
<langsyntaxhighlight lang="bbcbasic"> REM Used the following as official standard:
REM http://www.cnb.cz/cs/platebni_styk/iban/download/EBS204.pdf
 
Line 273 ⟶ 526:
num$=MID$(num$,8)
ENDWHILE
=VALmod$</langsyntaxhighlight>{{out}}
valid IBAN: GB82 WEST 1234 5698 7654 32
valid IBAN: GB82WEST12345698765432
Line 286 ⟶ 539:
invalid IBAN: US12 3456 7890 0987 6543 210 ***error!*** invalid country code: US
invalid IBAN: GR16 0110 1250 0000 0001 2300 695X ***error!*** invalid code length, expected length: 27
 
=={{header|Befunge}}==
 
<syntaxhighlight lang="befunge">>>" :NABI">:#,_>:~:"`"`48**-:55+-#v_$0::6g0>>8g-!\7g18g-!*!v>v>>
<<_#v:#78#`8#+<^+!!*-*84\-9:g8:p8\<oo>1#$-#<0$>>>#v_"dilav" ^#<<
>>^ >*-:20p9`9*1+55+**20g+"a"%10g1+00g%:4-!|^g6::_v#-*88:+1_vv>>
<<^+`"Z"\+`\"0"\*`\"A"\`"9":::\-*86:g8p01:<<40p00_v#!--+99g5<v<<
>>" si rebmun tahT">:#,_ 55+".",,@ >0"dilavni">>>
"-(&(/$$*$(*.-*.('$)*%0-&**.$'(.'/.+,''&&*.)**&,-.&.(*(*-!(%01-)
BFBBBBFFTNRRGGCCGCGGSSKSKSSDDHDHCPLPTLLLLPPAAVEIIAAAIEMMMNGMMMMI
ERGAHRIONLSOTRZYBRLIKIWMZAEOKREUHSBTRIVTUKLEDGESTLTZESEDCOEKUTRL</syntaxhighlight>
 
{{out}}
 
<pre>IBAN: GB82 WEST 1234 5698 7654 32
That number is valid.</pre>
 
<pre>IBAN: GB82 EAST 1234 5698 7654 32
That number is invalid.</pre>
 
=={{header|Bracmat}}==
<langsyntaxhighlight lang="bracmat">( ( IBAN-check
= table country cd len N c
. (AL.28) (AD.24) (AT.20) (AZ.28) (BE.16) (BH.22) (BA.20) (BR.29)
Line 338 ⟶ 610:
& IBAN-check$"GB82 WEST 1243 5698 7654 32"
& IBAN-check$"GB82 west 1243 5698 7654 32"
);</langsyntaxhighlight>{{out}}
wrong length
invalid country code: 'GX'
Line 349 ⟶ 621:
 
=={{header|C}}==
<langsyntaxhighlight Clang="c">#include <alloca.h>
#include <ctype.h>
#include <stdio.h>
Line 423 ⟶ 695:
 
/* Allocate space for the transformed IBAN. */
trans = alloca(sz + l + 1);
trans[sz + l] = 0;
 
Line 445 ⟶ 717:
 
return 0;
}</langsyntaxhighlight>{{out}}
iban 'GB82 WEST 1234 5698 7654 32' GB82TEST12345698765432
GB82WEST12345698765432 is valid.
GB82TEST12345698765432 is invalid.
 
=={{header|C++}}==
<lang cpp>#include <string>
#include <iostream>
#include <boost/algorithm/string.hpp>
#include <map>
#include <algorithm>
#include <cctype>
using namespace boost::algorithm ;
 
bool isValid ( const std::string &ibanstring )
{
static std::map<std::string, int> countrycodes
{ {"AL" , 28} , {"AD" , 24} , {"AT" , 20} , {"AZ" , 28 } ,
{"BE" , 16} , {"BH" , 22} , {"BA" , 20} , {"BR" , 29 } ,
{"BG" , 22} , {"CR" , 21} , {"HR" , 21} , {"CY" , 28 } ,
{"CZ" , 24} , {"DK" , 18} , {"DO" , 28} , {"EE" , 20 } ,
{"FO" , 18} , {"FI" , 18} , {"FR" , 27} , {"GE" , 22 } ,
{"DE" , 22} , {"GI" , 23} , {"GR" , 27} , {"GL" , 18 } ,
{"GT" , 28} , {"HU" , 28} , {"IS" , 26} , {"IE" , 22 } ,
{"IL" , 23} , {"IT" , 27} , {"KZ" , 20} , {"KW" , 30 } ,
{"LV" , 21} , {"LB" , 28} , {"LI" , 21} , {"LT" , 20 } ,
{"LU" , 20} , {"MK" , 19} , {"MT" , 31} , {"MR" , 27 } ,
{"MU" , 30} , {"MC" , 27} , {"MD" , 24} , {"ME" , 22 } ,
{"NL" , 18} , {"NO" , 15} , {"PK" , 24} , {"PS" , 29 } ,
{"PL" , 28} , {"PT" , 25} , {"RO" , 24} , {"SM" , 27 } ,
{"SA" , 24} , {"RS" , 22} , {"SK" , 24} , {"SI" , 19 } ,
{"ES" , 24} , {"SE" , 24} , {"CH" , 21} , {"TN" , 24 } ,
{"TR" , 26} , {"AE" , 23} , {"GB" , 22} , {"VG" , 24 } } ;
std::string teststring( ibanstring ) ;
erase_all( teststring , " " ) ; //defined in boost/algorithm/string.hpp
if ( countrycodes.find( teststring.substr(0 , 2 )) == countrycodes.end( ) )
return false ;
if ( teststring.length( ) != countrycodes[ teststring.substr( 0 , 2 ) ] )
return false ;
if (!all(teststring, is_alnum()))
return false ;
to_upper( teststring ) ;
std::rotate(teststring.begin(), teststring.begin() + 4, teststring.end());
 
std::string numberstring ;//will contain the letter substitutions
for (const auto& c : teststring)
{
if (std::isdigit(c))
numberstring += c ;
if (std::isupper(c))
numberstring += std::to_string(static_cast<int>(c) - 55);
}
//implements a stepwise check for mod 97 in chunks of 9 at the first time
// , then in chunks of seven prepended by the last mod 97 operation converted
//to a string
int segstart = 0 ;
int step = 9 ;
std::string prepended ;
long number = 0 ;
while ( segstart < numberstring.length( ) - step ) {
number = std::stol( prepended + numberstring.substr( segstart , step ) ) ;
int remainder = number % 97 ;
prepended = std::to_string( remainder ) ;
if ( remainder < 10 )
prepended = "0" + prepended ;
segstart = segstart + step ;
step = 7 ;
}
number = std::stol( prepended + numberstring.substr( segstart )) ;
return ( number % 97 == 1 ) ;
}
 
void SayValidity(const std::string& iban)
{
std::cout << iban << (isValid(iban) ? " is " : " is not ") << "valid\n";
}
 
int main( )
{
SayValidity("GB82 WEST 1234 5698 7654 32");
SayValidity("GB82TEST12345698765432");
return 0 ;
}</lang>{{out}}
GB82 WEST 1234 5698 7654 32 is valid!
GB82TEST12345698765432 is not valid!
 
=={{header|C sharp}}==
<langsyntaxhighlight lang="csharp"> public class IbanValidator : IValidateTypes
{
public ValidationResult Validate(string value)
Line 650 ⟶ 841:
{"VG", 24}
};
}</langsyntaxhighlight>Demonstrating:
<langsyntaxhighlight lang="csharp"> public class When_the_IbanValidator_is_told_to_Validate
{
[Fact]
Line 750 ⟶ 941:
Assert.Equal(ValidationResult.IsValid, result);
}
}</langsyntaxhighlight>
 
=={{header|C++}}==
<syntaxhighlight lang="cpp">#include <string>
#include <iostream>
#include <boost/algorithm/string.hpp>
#include <map>
#include <algorithm>
#include <cctype>
 
using namespace boost::algorithm;
 
bool isValid(const std::string &ibanstring) {
static std::map<std::string, int> countrycodes {
{"AL", 28}, {"AD", 24}, {"AT", 20}, {"AZ", 28 },
{"BE", 16}, {"BH", 22}, {"BA", 20}, {"BR", 29 },
{"BG", 22}, {"CR", 21}, {"HR", 21}, {"CY", 28 },
{"CZ", 24}, {"DK", 18}, {"DO", 28}, {"EE", 20 },
{"FO", 18}, {"FI", 18}, {"FR", 27}, {"GE", 22 },
{"DE", 22}, {"GI", 23}, {"GR", 27}, {"GL", 18 },
{"GT", 28}, {"HU", 28}, {"IS", 26}, {"IE", 22 },
{"IL", 23}, {"IT", 27}, {"KZ", 20}, {"KW", 30 },
{"LV", 21}, {"LB", 28}, {"LI", 21}, {"LT", 20 },
{"LU", 20}, {"MK", 19}, {"MT", 31}, {"MR", 27 },
{"MU", 30}, {"MC", 27}, {"MD", 24}, {"ME", 22 },
{"NL", 18}, {"NO", 15}, {"PK", 24}, {"PS", 29 },
{"PL", 28}, {"PT", 25}, {"RO", 24}, {"SM", 27 },
{"SA", 24}, {"RS", 22}, {"SK", 24}, {"SI", 19 },
{"ES", 24}, {"SE", 24}, {"CH", 21}, {"TN", 24 },
{"TR", 26}, {"AE", 23}, {"GB", 22}, {"VG", 24 }
};
std::string teststring(ibanstring);
erase_all(teststring, " "); //defined in boost/algorithm/string.hpp
if (countrycodes.find(teststring.substr(0, 2)) == countrycodes.end())
return false;
if (teststring.length() != countrycodes[teststring.substr(0, 2)])
return false;
if (!all(teststring, is_alnum()))
return false;
to_upper(teststring);
std::rotate(teststring.begin(), teststring.begin() + 4, teststring.end());
 
std::string numberstring; // will contain the letter substitutions
for (const auto &c : teststring) {
if (std::isdigit(c))
numberstring += c;
if (std::isupper(c))
numberstring += std::to_string(static_cast<int>(c) - 55);
}
// implements a stepwise check for mod 97 in chunks of 9 at the first time,
// then in chunks of seven prepended by the last mod 97 operation converted
// to a string
int segstart = 0;
int step = 9;
std::string prepended;
long number = 0;
while (segstart < numberstring.length() - step) {
number = std::stol(prepended + numberstring.substr(segstart, step));
int remainder = number % 97;
prepended = std::to_string(remainder);
if (remainder < 10)
prepended = "0" + prepended;
segstart = segstart + step;
step = 7;
}
number = std::stol(prepended + numberstring.substr(segstart));
return (number % 97 == 1);
}
 
void SayValidity(const std::string &iban) {
std::cout << iban << (isValid(iban) ? " is " : " is not ") << "valid\n";
}
 
int main() {
SayValidity("GB82 WEST 1234 5698 7654 32");
SayValidity("GB82TEST12345698765432");
return 0;
}</syntaxhighlight>{{out}}
GB82 WEST 1234 5698 7654 32 is valid!
GB82TEST12345698765432 is not valid!
 
=={{header|Caché ObjectScript}}==
 
<langsyntaxhighlight lang="cos">Class Utils.Validate [ Abstract ]
{
 
Line 851 ⟶ 1,121:
}
 
}</langsyntaxhighlight>{{out|Examples}}
<pre>USER>For { Read iban Quit:iban="" Write " => ", ##class(Utils.Validate).VerifyIBAN(iban), ! }
GB82 WEST 1234 5698 7654 32 => 1
Line 864 ⟶ 1,134:
 
=={{header|Clojure}}==
<langsyntaxhighlight Clojurelang="clojure">(def explen
{"AL" 28 "AD" 24 "AT" 20 "AZ" 28 "BE" 16 "BH" 22 "BA" 20 "BR" 29
"BG" 22 "CR" 21 "HR" 21 "CY" 28 "CZ" 24 "DK" 18 "DO" 28 "EE" 20
Line 887 ⟶ 1,157:
 
(prn (valid-iban? "GB82 WEST 1234 5698 7654 32") ; true
(valid-iban? "GB82 TEST 1234 5698 7654 32")) ; false</langsyntaxhighlight>
 
=={{header|COBOL}}==
{{works with|OpenCOBOL}}
<langsyntaxhighlight lang="cobol"> IDENTIFICATION DIVISION.
PROGRAM-ID. iban-main.
 
Line 1,051 ⟶ 1,321:
END PROGRAM create-iban-number.
 
END PROGRAM validate-iban.</langsyntaxhighlight>{{out}}
<pre>
GB82 WEST 1234 5698 7654 32 is valid.
Line 1,058 ⟶ 1,328:
 
=={{header|Common Lisp}}==
<langsyntaxhighlight lang="lisp">
;;
;; List of the IBAN code lengths per country.
Line 1,120 ⟶ 1,390:
(= 1 (mod (IBAN-to-integer X) 97)))))
(validp (remove #\Space iban))))
</syntaxhighlight>
</lang>
'''Output:'''
<pre>
Line 1,133 ⟶ 1,403:
=={{header|D}}==
{{trans|Python}}
<langsyntaxhighlight lang="d">import std.stdio, std.string, std.regex, std.conv, std.bigint,
std.algorithm, std.ascii;
 
Line 1,169 ⟶ 1,439:
"GB82 TEST 1234 5698 7654 32"])
writefln("%s validation is: %s", account, account.validIBAN);
}</langsyntaxhighlight>{{out}}
<pre>GB82 WEST 1234 5698 7654 32 validation is: true
GB82 TEST 1234 5698 7654 32 validation is: false</pre>
 
=={{header|DBL}}==
<syntaxhighlight lang="dbl">;
; Validate IBAN for DBL version 4 by Dario B.
;
; Compile with "dbl -r" to reinitialize all data each time
; the module (main or subroutine) is entered.
;
RECORD
 
J, D5
ISVALID, D1
IBAN, A35,'GB82 WEST 1234 5698 7654 32'
, A35,'GB82 TEST 1234 5698 7654 32'
, A35,'GR16 0110 1250 0000 0001 2300 695'
, A35,'GB29 NWBK 6016 1331 9268 19'
, A35,'SA03 8000 0000 6080 1016 7519'
, A35,'CH93 0076 2011 6238 5295 7'
, A35,'IL62 0108 0000 0009 9999 999'
, A35,'US12 3456 7890 0987 6543 210'
, A35,'GR16 0110 1250 0000 0001 2300 695X'
 
 
PROC
;-------------------------------------------------------------------------------
 
XCALL FLAGS (0007000000,1) ;Suppress STOP message
 
OPEN (1,O,'TT:') ;Open video
 
FOR J=1 UNTIL 9
DO BEGIN
XCALL CHECK_IBAN (IBAN(J),ISVALID)
IF (ISVALID.EQ.1)
THEN DISPLAY (1,IBAN(J),' is valid',10)
ELSE DISPLAY (1,IBAN(J),' is not valid',10)
END
 
 
CLOSE 1
END
 
;===============================================================================
; CHECK AND VALIDATE IBAN SUBROUTINE
;===============================================================================
 
SUBROUTINE CHECK_IBAN
 
IBAN, A ;IBAN code
ISVALID, D ;0=is not valid 1=is valid
 
 
 
RECORD
 
K, D5
J, D5
D2, D2
D3, D3
D9, D9
A9, A9
 
IBANC, A35
IINT, A80
PARTS, D2
MOD, D5
 
.DEFINE NC,75 ;numbers of ISO / LEN in table
ISOCK, [NC]A4,'AD24','AE23','AL28','AT20','AZ28','BA20','BE16','BG22','BH22','BR29',
&'BY28','CH21','CR22','CY28','CZ24','DE22','DK18','DO28','EE20','ES24',
&'FI18','FO18','FR27','GB22','GE22','GI23','GL18','GR27','GT28','HR21',
&'HU28','IE22','IL23','IQ23','IS26','IT27','JO30','KW30','KZ20','LB28',
&'LC32','LI21','LT20','LU20','LV21','MC27','MD24','ME22','MK19','MR27',
&'MT31','MU30','NL18','NO15','PK24','PL28','PS29','PT25','QA29','RO24',
&'RS22','SA24','SC31','SE24','SI19','SK24','SM27','ST25','SV28','TL23',
&'TN24','TR26','UA29','VG24','XK20'
 
 
PROC
;-------------------------------------------------------------------------------
 
CLEAR IBANC,IINT ;Not required when compiled with dbl -r
 
;Remove blanks
K=
FOR J=1 UNTIL %TRIM(IBAN) DO IF (IBAN(J:1).NE.' ')
BEGIN
INCR K
IBANC(K:1)=IBAN(J:1)
END
 
;Check ISO code and len
UPCASE IBANC
FOR J=1 UNTIL NC DO IF (IBANC(1:2).EQ.ISOCK[J](1:2)) EXITLOOP
IF (J.GT.NC)
BEGIN
;ISO not found in table, returns ISVALID=0
ISVALID=
XRETURN
END
 
D2=ISOCK[J](3:2)
IF (%TRIM(IBANC).NE.D2)
BEGIN
;wrong len returns ISVALID=0
ISVALID=
XRETURN
END
 
; Now, do this
; IBAN: GB82WEST12345698765432
; Rearrange: WEST12345698765432GB82
; Convert to integer: 3214282912345698765432161182
; Compute remainder: 3214282912345698765432161182 mod 97 = 1
 
;Move the first four characters to the end
IBANC(%TRIM(IBANC)+1:4)=IBANC(1:4)
IBANC=IBANC(5,$LEN(IBANC))
 
 
;Convert A to 10, B to 11 ... Z
K=1
FOR J=1 UNTIL %TRIM(IBANC)
DO BEGIN
IF (IBANC(J:1).GE.'A'.AND.IBANC(J:1).LE.'Z')
THEN BEGIN
XCALL DECML (IBANC(J:1),D3)
IINT(K:2)=D3-55,'XX'
K=K+2
END
ELSE BEGIN
IINT(K:1)=IBANC(J:1)
INCR K
END
END
 
;Calculate the mod 97 of large number.
;Implements a stepwise check for mod 97 in chunks of 9 at the first time,
;then in chunks of seven prepended by the last mod 97 operation converted
;to a string
PARTS=1+(%TRIM(IINT)-9)/7
IF ((PARTS-1)*7.LT.%TRIM(IINT)-9) INCR PARTS
 
FOR J=1 UNTIL PARTS
DO BEGIN
IF (J.EQ.1) THEN A9=IINT(1:9)
ELSE BEGIN
A9(1:2)=MOD,'XX'
A9(3:7)=IINT(10+(J-2)*7:7)
END
D9=A9
MOD=D9-(D9/97)*97
END
 
IF (MOD.EQ.1) ISVALID=1
ELSE ISVALID=
XRETURN
END</syntaxhighlight>
{{out}}
<pre>GB82 WEST 1234 5698 7654 32 is valid
GB82 TEST 1234 5698 7654 32 is not valid
GR16 0110 1250 0000 0001 2300 695 is valid
GB29 NWBK 6016 1331 9268 19 is valid
SA03 8000 0000 6080 1016 7519 is valid
CH93 0076 2011 6238 5295 7 is valid
IL62 0108 0000 0009 9999 999 is valid
US12 3456 7890 0987 6543 210 is not valid
GR16 0110 1250 0000 0001 2300 695X is not valid</pre>
 
=={{header|Elixir}}==
{{trans|Ruby}}
<langsyntaxhighlight lang="elixir">defmodule IBAN do
@len %{ AL: 28, AD: 24, AT: 20, AZ: 28, BE: 16, BH: 22, BA: 20, BR: 29,
BG: 22, CR: 21, HR: 21, CY: 28, CZ: 24, DK: 18, DO: 28, EE: 20,
Line 1,210 ⟶ 1,648:
"GB82 TEST 1234 5698 7654 32",
"ZZ12 3456 7890 1234 5678 12" ]
|> Enum.each(fn iban -> IO.puts "#{IBAN.valid?(iban)}\t#{iban}" end)</langsyntaxhighlight>
 
{{out}}
Line 1,223 ⟶ 1,661:
 
=={{header|F_Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">open System
open System.Text.RegularExpressions
 
Line 1,274 ⟶ 1,712:
|> function | Some(_) -> "a valid IBAN" | None -> "an invalid IBAN"
|> printfn "%s is %s" iban
0</langsyntaxhighlight>{{out}}
>Rosetta.exe "GB82 WEST 1234 5698 7654 32"
GB82 WEST 1234 5698 7654 32 is a valid IBAN
Line 1,280 ⟶ 1,718:
>Rosetta.exe "GB82 TEST 1234 5698 7654 32"
GB82 TEST 1234 5698 7654 32 is an invalid IBAN
 
=={{header|Factor}}==
<syntaxhighlight lang="factor">USING: assocs combinators.short-circuit formatting kernel math
math.parser regexp sequences sets qw unicode ;
IN: rosetta-code.iban
 
<PRIVATE
 
CONSTANT: countries H{
{ 15 qw{ NO } }
{ 16 qw{ BE } }
{ 18 qw{ DK FO FI GL NL } }
{ 19 qw{ MK SI } }
{ 20 qw{ AT BA EE KZ LT LU } }
{ 21 qw{ CR HR LV LI CH } }
{ 22 qw{ BH BG GE DE IE ME RS GB } }
{ 23 qw{ GI IL AE } }
{ 24 qw{ AD CZ MD PK RO SA SK ES SE TN VG } }
{ 25 qw{ PT } }
{ 26 qw{ IS TR } }
{ 27 qw{ FR GR IT MR MC SM } }
{ 28 qw{ AL AZ CY DO GT HU LB PL } }
{ 29 qw{ BR PS } }
{ 30 qw{ KW MU } }
{ 31 qw{ MT } }
}
 
: valid-chars? ( str -- ? ) R/ [A-Z0-9]+/ matches? ;
 
: valid-length? ( str -- ? )
[ 2 head ] [ length ] bi countries at member? ;
 
: valid-checksum? ( str -- ? )
4 cut swap append [ digit> number>string ] { } map-as
concat string>number 97 mod 1 = ;
 
PRIVATE>
 
: valid-iban? ( str -- ? )
" " without {
[ valid-chars? ] [ valid-length? ] [ valid-checksum? ]
} 1&& ;
 
: iban-demo ( -- )
"GB82 WEST 1234 5698 7654 32"
"GB82 TEST 1234 5698 7654 32"
[
dup valid-iban? "may be a valid" "is an invalid" ?
"%s %s IBAN\n" printf
] bi@ ;
 
MAIN: iban-demo</syntaxhighlight>
{{out}}
<pre>
GB82 WEST 1234 5698 7654 32 may be a valid IBAN
GB82 TEST 1234 5698 7654 32 is an invalid IBAN
</pre>
 
=={{header|Forth}}==
{{Works with|4tH|3.62.3}}
<syntaxhighlight lang="text">include lib/ulcase.4th \ for S>UPPER
include lib/triple.4th \ for UT/MOD
include lib/cstring.4th \ for C/STRING
Line 1,320 ⟶ 1,815:
;
 
checkiban</langsyntaxhighlight>
{{Out}}
<pre>linux:~> pp4th -x chkiban.4th
Line 1,328 ⟶ 1,823:
Enter your IBAN: GB82TEST12345698765432
Invalid</pre>
 
=={{header|Fortran}}==
<syntaxhighlight lang="fortran">
program ibancheck
 
use ISO_FORTRAN_ENV
 
implicit none
 
character(4), dimension(75) :: cc = (/ &
"AD24","AE23","AL28","AT20","AZ28","BA20","BE16","BG22","BH22","BR29", &
"BY28","CH21","CR22","CY28","CZ24","DE22","DK18","DO28","EE20","ES24", &
"FI18","FO18","FR27","GB22","GE22","GI23","GL18","GR27","GT28","HR21", &
"HU28","IE22","IL23","IQ23","IS26","IT27","JO30","KW30","KZ20","LB28", &
"LC32","LI21","LT20","LU20","LV21","MC27","MD24","ME22","MK19","MR27", &
"MT31","MU30","NL18","NO15","PK24","PL28","PS29","PT25","QA29","RO24", &
"RS22","SA24","SC31","SE24","SI19","SK24","SM27","ST25","SV28","TL23", &
"TN24","TR26","UA29","VG24","XK20" /)
 
character(34), dimension(12) :: ibans = (/ "GB82 WEST 1234 5698 7654 32 ", &
"GB82WEST12345698765432 ", &
"gb82 west 1234 5698 7654 32 ", &
"GB82 TEST 1234 5698 7654 32 ", &
"GR16 0110 1250 0000 0001 2300 695 ", &
"GB29 NWBK 6016 1331 9268 19 ", &
"SA03 8000 0000 6080 1016 7519 ", &
"CH93 0076 2011 6238 5295 7 ", &
"IL62 0108 0000 0009 9999 999 ", &
"IL62-0108-0000-0009-9999-999 ", &
"US12 3456 7890 0987 6543 210 ", &
"GR16 0110 1250 0000 0001 2300 695X" /)
 
integer :: i
do i=1, size(ibans)
if (checkIBAN(trim(ibans(i)))) then
print *, " valid IBAN: ", trim(ibans(i))
else
print *, "invalid IBAN: ", trim(ibans(i))
end if
end do
 
return
contains
 
function checkIBAN(ibancode) result(valid)
character(len=*), intent(in) :: ibancode
character(len=len(ibancode)) :: iban
logical :: valid
integer(int32) :: j, ascii, ibanSize
character(100) :: ibanRearrange, ibantoint
character(2) :: temp
valid = .false.
 
iban = remove_blanks(ibancode)
ibanSize = checkCountryCode(iban)
if (ibanSize == len(trim(iban))) then
ibanRearrange = iban(5:ibanSize)//iban(1:4)
ibantoint = ""
do j=1, ibanSize
ascii = ichar(ibanRearrange(j:j))
if ((ascii >= 65) .and. (ascii<=90)) then
write (temp,fmt='(I2)') ascii-55
ibantoint = trim(ibantoint) // temp
else
ibantoint = trim(ibantoint) // ibanRearrange(j:j)
end if
end do
if (mod97(ibantoint) == 1) then
valid = .true.
end if
end if
end function checkIBAN
function mod97(strint) result(res)
character(len=*), intent(in) :: strint
integer :: i, num, res
res = 0
do i=1, len(trim(strint))
read(strint(i:i),*) num
res = mod((res*10 + num),97);
end do
end function mod97
 
function checkCountryCode(iban) result(ibanlength)
character(len=*), intent(in) :: iban
integer(int16) :: ibanlength, i
ibanlength = 0
do i=1, size(cc)
if (iban(1:2) == cc(i)(1:2)) then
read(cc(i)(3:4),*) ibanlength
exit
end if
end do
end function checkCountryCode
Recursive Function Stripper(string,ch) Result(stripped)
Implicit None
character(len=*), intent(in) :: string
character, intent(in) :: ch
character(:), allocatable :: stripped
 
IF (LEN(string)==1) THEN
IF (string==ch) THEN
stripped = ''
ELSE
stripped = string
END IF
ELSE
IF (string(1:1)==ch) THEN
stripped = stripper(string(2:),ch)
ELSE
stripped = string(1:1)//stripper(string(2:),ch)
END IF
END IF
END Function stripper
 
Function Remove_Blanks(string) Result(stripped)
Implicit None
character(len=*), intent(in) :: string
character(:), allocatable :: stripped
 
stripped = trim(Stripper(trim(Stripper(string,' ')),achar(9)))
END Function Remove_Blanks
 
end program ibancheck
</syntaxhighlight>
 
{{out}}
<pre>
valid IBAN: GB82 WEST 1234 5698 7654 32
valid IBAN: GB82WEST12345698765432
invalid IBAN: gb82 west 1234 5698 7654 32
invalid IBAN: GB82 TEST 1234 5698 7654 32
valid IBAN: GR16 0110 1250 0000 0001 2300 695
valid IBAN: GB29 NWBK 6016 1331 9268 19
valid IBAN: SA03 8000 0000 6080 1016 7519
valid IBAN: CH93 0076 2011 6238 5295 7
valid IBAN: IL62 0108 0000 0009 9999 999
invalid IBAN: IL62-0108-0000-0009-9999-999
invalid IBAN: US12 3456 7890 0987 6543 210
invalid IBAN: GR16 0110 1250 0000 0001 2300 695X
</pre>
 
=={{header|FreeBASIC}}==
<syntaxhighlight lang="freebasic">' FB 1.05.0 Win64
 
' List updated to release 72, 25 November 2016, of IBAN Registry (75 countries)
Dim Shared countryCodes As String
countryCodes = _
"AD24 AE23 AL28 AT20 AZ28 BA20 BE16 BG22 BH22 BR29 BY28 CH21 CR22 CY28 CZ24 DE22 " _
"DK18 DO28 EE20 ES24 FI18 FO18 FR27 GB22 GE22 GI23 GL18 GR27 GT28 HR21 HU28 IE22 " _
"IL23 IQ23 IS26 IT27 JO30 KW30 KZ20 LB28 LC32 LI21 LT20 LU20 LV21 MC27 MD24 ME22 " _
"MK19 MR27 MT31 MU30 NL18 NO15 PK24 PL28 PS29 PT25 QA29 RO24 RS22 SA24 SC31 SE24 " _
"SI19 SK24 SM27 ST25 SV28 TL23 TN24 TR26 UA29 VG24 XK20"
 
Function checkCountryCode(cc As String) As Boolean
Return Instr(countryCodes, cc)
End Function
 
' To avoid having to use the GMP library, a piece-wise calculation is used
Function mod97(s As String) As UInteger
Dim r As UInteger = ValULng(Left(s, 9)) Mod 97
Dim start As UInteger = 10
While start < Len(s)
r = ValULng(r & Mid(s, start, 7)) Mod 97
start += 7
Wend
Return r
End Function
 
Function validateIban(iban As Const String) As Boolean
' remove spaces from IBAN
Dim s As String = iban
Dim count As Integer = 0
For i As Integer = 0 To Len(s) - 1
If s[i] = 32 Then
For j As Integer = i + 1 To Len(s) - 1
s[j - 1] = s[j]
Next
count += 1
End If
If i = Len(s) - 1 - count Then Exit For
Next i
If count > 0 Then
s[Len(s) - count] = 0
Dim p As UInteger Ptr = CPtr(UInteger Ptr, @s)
*(p + 1) = Len(s) - count ''change length of string in descriptor
End If
 
' check country code
Dim isValid As Boolean = checkCountryCode(Left(s, 2) + Str(Len(s)))
If Not isValid Then Return False
 
' move first 4 characters to end
s = Mid(s, 5) + Left(s, 4)
 
' replace A to Z with numbers 10 To 35
For i As Integer = Len(s) To 1 Step -1
If s[i - 1] >= 65 AndAlso s[i - 1] <= 90 Then
s = Left(s, i - 1) + Str(s[i - 1] - 55) + Mid(s, i + 1)
End If
Next
' do mod97 calculation
Return mod97(s) = 1 '' remainder needs to be 1 for validity
End Function
 
Dim As String ibans(1 To 2) = {"GB82 WEST 1234 5698 7654 32", "GB82 TEST 1234 5698 7654 32"}
For i As Integer = 1 To 2
Dim isValid As Boolean = validateIban(ibans(i))
Print ibans(i); IIf(isValid, " : may be valid", " : is not valid")
Next
 
Print
Print "Press any key to quit"
Sleep</syntaxhighlight>
 
{{out}}
<pre>
GB82 WEST 1234 5698 7654 32 : may be valid
GB82 TEST 1234 5698 7654 32 : is not valid
</pre>
 
=={{header|Free Pascal}}==
{{libheader|GMP}}
<syntaxhighlight lang="delphi">{$mode objFPC}
 
uses
// for delSpace function
strUtils,
// GNU multiple-precision library
GMP;
 
var
/// this trie contains the correct IBAN length depending on the country code
IBANLengthInCountry: array['A'..'Z', 'A'..'Z'] of integer;
 
type
/// Human-readable representation of an IBAN without spaces
IBANRepresentation = string[34];
 
{
determines whether an IBANRepresentation is technically potentially correct
\param sample the human-readable IBAN representation
\return \param sample constains less than the most detectable errors
}
function isLegal(sample: IBANRepresentation): Boolean;
function checksumCorrect(sample: IBANRepresentation): Boolean;
type
digitSequence = string[68];
function convertLetters(const sequence: IBANRepresentation): digitSequence;
var
i: integer;
transliteration: string[2];
begin
// initialize length to zero
result := '';
for i := 1 to length(sequence) do
begin
// by default assume it is a Western-Arabic digit
transliteration := sequence[i];
// otherwise we’ll need to transliterate the Latin alphabet character
if not (sequence[i] in ['0'..'9']) then
begin
writeStr(transliteration, ord(sequence[i]) - ord('A') + 10);
end;
// appending transliteration to result also changes the length field
result := result + transliteration;
end;
end;
var
i, k: MPInteger;
begin
k := 97;
// put first four characters toward end
writeStr(sample, sample[5..length(sample)], sample[1..4]);
// interpret converted string as integer to base 10
Z_set_str(i, convertLetters(sample), 10);
i := Z_mod(i, k);
k := 1;
checksumCorrect := Z_cmp(i, k) = 0;
end;
begin
sample := upCase(sample);
{$push}
// just for emphasis: by default the FPC performs lazy evaluation
{$boolEval off}
isLegal := (length(sample) = IBANLengthInCountry[sample[1], sample[2]])
and checksumCorrect(sample);
{$pop}
end;
 
// === MAIN ==============================================================
begin
// for the sake of merely achieving the Rosetta Code Task
IBANLengthInCountry['G', 'B'] := 22;
// note, strings longer than 34 characters will be silently clipped
writeLn(isLegal(delSpace('GB82 WEST 1234 5698 7654 32')));
end.</syntaxhighlight>
{{out}}
<pre>TRUE</pre>
 
=={{header|Go}}==
 
<syntaxhighlight lang="go">package main
<lang Go>
package main
 
import (
"fmtregexp"
"strings"
"strconvtesting"
"math/big"
)
 
var lCodelengthByCountryCode = map[string]int {
"AL": 28, "AD": 24, "AT": 20, "AZ": 28, "BE": 16, "BH": 22, "BA": 20, "BR": 29,
"BGBA": 2220, "CRBR": 2129, "HRBG": 2122, "CYCR": 2821, "CZHR": 2421, "DK": 18, "DOCY": 28, "EE": 20,
"FOCZ": 1824, "FIDK": 18, "FRDO": 2728, "GEEE": 2220, "DEFO": 2218, "GI": 23, "GR": 27, "GLFI": 18,
"GTFR": 2827, "HUGE": 2822, "IS": 26, "IEDE": 22, "ILGI": 23, "ITGR": 27, "KZ": 20, "KWGL": 3018,
"LVGT": 2128, "LBHU": 28, "LI": 21, "LT": 20, "LUIS": 2026, "MKIE": 1922, "MTIL": 3123, "MRIT": 27,
"MUKZ": 3020, "MCKW": 27, "MD": 24, "ME": 2230, "NLLV": 1821, "NOLB": 1528, "PKLI": 2421, "PSLT": 2920,
"PLLU": 2820, "PTMK": 2519, "ROMT": 2431, "SMMR": 27, "SAMU": 2430, "RSMC": 22, "SK": 24, "SI": 1927,
"ESMD": 24, "SEME": 2422, "CHNL": 2118, "TNNO": 2415, "TRPK": 2624, "AEPS": 23, "GB": 22, "VG": 2429,
"PL": 28, "PT": 25, "RO": 24, "SM": 27, "SA": 24, "RS": 22,
"SK": 24, "SI": 19, "ES": 24, "SE": 24, "CH": 21, "TN": 24,
"TR": 26, "AE": 23, "GB": 22, "VG": 24,
}
 
varfunc sCodeisValidIBAN(iban = map[string]int) bool {
if len(iban) < 4 {
"1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9,
return false
"A": 10, "B": 11, "C": 12, "D": 13, "E": 14, "F": 15, "G": 16,
}
"H": 17, "I": 18, "J": 19, "K": 20, "L": 21, "M": 22, "N": 23,
iban = regexp.MustCompile(`\s+`).ReplaceAllString(iban, "")
"O": 24, "P": 25, "Q": 26, "R": 27, "S": 28, "T": 29, "U": 30,
iban = strings.ToUpper(iban)
"V": 31, "W": 32, "X": 33, "Y": 34, "Z": 35,
}
 
if ibanLen := lengthByCountryCode[iban[0:2]]; ibanLen == len(iban) {
func main() {
return false
var iban string
var r, s, t, st []string
u := new(big.Int)
v := new(big.Int)
w := new(big.Int)
iban = "GB82 TEST 1234 5698 7654 32"
r = strings.Split(iban, " ")
s = strings.Split(r[0], "")
t = strings.Split(r[1], "")
st = []string{ strconv.Itoa(sCode[t[0]]),
strconv.Itoa(sCode[t[1]]),
strconv.Itoa(sCode[t[2]]),
strconv.Itoa(sCode[t[3]]),
strings.Join(r[2:6], ""),
strconv.Itoa(sCode[s[0]]),
strconv.Itoa(sCode[s[1]]),
strings.Join(s[2:4], ""),
}
iban = iban[4:] + iban[:4]
 
result := 0
u.SetString(strings.Join(st, ""), 10)
for _, ch := range iban {
v.SetInt64(97)
var n int
w.Mod(u, v)
if '0' <= ch && ch <= '9' {
n = int(ch) - '0'
if w.Uint64() == 1 && lCode[strings.Join(s[0:2], "")] == len(strings.Join(r, "")) {
} else if 'A' <= ch && ch <= 'Z' {
fmt.Printf("IBAN %s looks good!\n", iban)
n = 10 + int(ch) - 'A'
} else {
} else {
fmt.Printf("IBAN %s looks wrong!\n", iban)
return false
}
 
if n < 10 {
result = (10*result + n) % 97
} else {
result = (100*result + n) % 97
}
}
return result == 1
}
</lang>
 
func TestIsValidIBAN(t *testing.T) {
<pre>
tests := []struct {
IBAN GB82 WEST 1234 5698 7654 32 looks good!
iban string
IBAN GB82 TEST 1234 5698 7654 32 looks wrong!
valid bool
IBAN CH93 0076 2011 6238 5295 7 looks good!
}{
</pre>
{"GB82 WEST 1234 5698 7654 32", true},
{"GB82 TEST 1234 5698 7654 32", false},
}
for _, test := range tests {
if isValidIBAN(test.iban) == test.valid {
return
}
t.Errorf("Expected %q to be %v", test.iban, test.valid)
}
}
</syntaxhighlight>
 
=={{header|Groovy}}==
<langsyntaxhighlight lang="groovy">def validateIBAN(String iban) {
def iso = [AL: 28, AD: 24, AT: 20, AZ: 28, BE: 16, BH: 22, BA: 20, BR: 29, BG: 22,
HR: 21, CY: 28, CZ: 24, DK: 18, DO: 28, EE: 20, FO: 18, FI: 18, FR: 27, GE: 22, DE: 22, GI: 23,
Line 1,417 ⟶ 2,223:
def number = iban.collect { Character.digit(it as char, 36) }.join('')
(number as BigInteger).mod(97) == 1
}</langsyntaxhighlight>
 
Testing:
<langsyntaxhighlight lang="groovy">[ 'GB82 WEST 1234 5698 7654 32',
'GB82 TEST 1234 5698 7654 32',
'GB81 WEST 1234 5698 7654 32',
Line 1,426 ⟶ 2,232:
'CH93 0076 2011 6238 5295 7' ].each { iban ->
println "$iban is ${validateIBAN(iban) ? 'valid' : 'invalid'}"
}</langsyntaxhighlight>
{{output}}
<pre>GB82 WEST 1234 5698 7654 32 is valid
Line 1,436 ⟶ 2,242:
=={{header|Haskell}}==
This program uses the Maybe and Either monads to handle failures. Values of type 'Maybe a' can contain 'Nothing' (no value) or 'Just a' (a value of type 'a'). Values of type 'Either a b' contain 'Left b' (usually indicating failure) or 'Right c' (usually indicating success).
<langsyntaxhighlight Haskelllang="haskell">import Data.Char (toUpper)
import Data.Maybe (fromJust)
 
validateIBAN :: String -> Either String String
Line 1,476 ⟶ 2,283:
-- convert the result to an integer
p4 :: Integer
p4 = read $ concat $ convertLettersmap convertLetter p3
convertLettersconvertLetter []x | x `elem` digits = [x]
| otherwise = fromJust $ lookup x replDigits
convertLetters (x:xs)
| x `elem` digits = [x] : convertLetters xs
| otherwise = let (Just ys) = lookup x replDigits
in ys : convertLetters xs
-- see if the number is valid
check = if sane
Line 1,490 ⟶ 2,294:
 
invalidBecause reason = Left $ "Invalid IBAN number " ++ xs ++
": " ++ reason</langsyntaxhighlight>{{out}}
<pre>
validateIBAN "GB82 WEST 1234 5698 7654 32"
Line 1,510 ⟶ 2,314:
Left "Invalid IBAN number GB82 _EST 1234 5698 7654 32: Number contains illegal digits."
</pre>
 
=={{header|IS-BASIC}}==
<syntaxhighlight lang="is-basic">100 PROGRAM "IBAN.bas"
110 STRING CO$(1 TO 93)*2
120 NUMERIC LG(1 TO 93)
130 FOR I=1 TO 93
140 READ CO$(I),LG(I)
150 NEXT
160 DO
170 PRINT :PRINT "IBAN code: ":INPUT PROMPT ">":IB$
180 IF IB$="" THEN EXIT DO
190 IF IBAN(IB$) THEN
200 PRINT "CRC ok."
210 ELSE
220 SET #102:INK 3:PRINT "CRC error.":SET #102:INK 1
230 END IF
240 LOOP
250 DEF TRIM$(S$)
260 LET T$=""
270 FOR I=1 TO LEN(S$)
280 IF S$(I)>CHR$(47) AND S$(I)<CHR$(91) THEN LET T$=T$&S$(I)
290 NEXT
300 LET TRIM$=T$
310 END DEF
320 DEF IBAN(IB$)
330 LET IB$=TRIM$(UCASE$(IB$)):LET T$="":LET M,IBAN=0:LET N=FIND(IB$(1:2))
340 IF N=0 THEN PRINT "Invalid country code.":EXIT DEF
350 IF LEN(IB$)<>LG(N) THEN PRINT "Number length does not match.":EXIT DEF
360 LET IB$=IB$&IB$(1:4):LET IB$=IB$(5:)
370 CALL CONVERT(IB$)
380 FOR I=1 TO LEN(IB$)
390 LET T$=STR$(M)&IB$(I)
400 LET M=MOD(VAL(T$),97)
410 NEXT
420 IF M=1 THEN LET IBAN=-1
430 END DEF
440 DEF FIND(S$)
450 LET FIND=0
460 LET BO=LBOUND(CO$):LET UP=UBOUND(CO$)
470 DO
480 LET K=INT((BO+UP)/2)
490 IF CO$(K)<S$ THEN LET BO=K+1
500 IF CO$(K)>S$ THEN LET UP=K-1
510 LOOP WHILE BO<=UP AND CO$(K)<>S$
520 IF BO<=UP THEN LET FIND=K
530 END DEF
540 DEF CONVERT(REF S$)
550 LET T$=""
560 FOR I=1 TO LEN(S$)
570 IF S$(I)>CHR$(64) AND S$(I)<CHR$(91) THEN
580 LET T$=T$&STR$(ORD(S$(I))-55)
590 ELSE
600 LET T$=T$&S$(I)
610 END IF
620 NEXT
630 LET S$=T$
640 END DEF
650 DATA AD,24,AE,23,AL,28,AO,25,AT,20,AZ,28,BA,20,BE,16,BF,28,BG,22,BH,22,BI,16,BJ,28,BR,29,BY,28,CG,27,CH,21,CI,28,CM,27,CR,22,CV,25,CY,28,CZ,24,DE,22,DK,18,DO,28,DZ,24,EE,20,EG,27,ES,24,FI,18,FO,18,FR,27,GA,27,GB,22,GE,22,GI,23,GL,18
660 DATA GR,27,GT,28,HN,28,HR,21,HU,28,IE,22,IL,23,IR,26,IS,26,IT,27,JO,30,KM,27,KW,30,KZ,20,LB,28,LI,21,LT,20,LU,20,LV,21,MA,28,MC,27,MD,24,ME,22,MG,27,MK,19,ML,28,MR,27,MT,31,MU,30,MZ,25,NE,28,NI,32,NL,18,NO,15,PK,24,PL,28,PS,29,PT,25
670 DATA QA,29,RO,24,RS,22,SA,24,SE,24,SI,19,SK,24,SM,27,SN,28,TD,27,TG,28,TL,23,TN,24,TR,26,UA,29,VG,24,XK,20</syntaxhighlight>
 
=={{header|J}}==
<langsyntaxhighlight Jlang="j">NB. delete any blank characters
delblk =. #~ ' '&~:
NB. rearrange
Line 1,546 ⟶ 2,410:
NB. IBAN
iban =: quads @: ibancheck
</langsyntaxhighlight>{{out}}
<pre>
iban 'GB82 WEST 1234 5698 7654 32'
Line 1,560 ⟶ 2,424:
 
=={{header|Java}}==
{{works with|Java|78+}}
<langsyntaxhighlight java5lang="java">import java.math.BigInteger;
import java.util.*;
 
public class IBAN {
private static final Map<String, Integer>DEFSTRS = isoPairs;""
+ "AL28 AD24 AT20 AZ28 BE16 BH22 BA20 BR29 BG22 "
 
static final String iso = "AL28 AD24 AT20 AZ28 BE16 BH22 BA20 BR29 BG22 "
+ "HR21 CY28 CZ24 DK18 DO28 EE20 FO18 FI18 FR27 GE22 DE22 GI23 "
+ "GL18 GT28 HU28 IS26 IE22 IL23 IT27 KZ20 KW30 LV21 LB28 LI21 "
Line 1,573 ⟶ 2,436:
+ "PS29 PL28 PT25 RO24 SM27 SA24 RS22 SK24 SI19 ES24 SE24 CH21 "
+ "TN24 TR26 AE23 GB22 VG24 GR27 CR21";
private static final Map<String, Integer> DEFINITIONS = new HashMap<>();
 
static {
isoPairsfor =(String newdefinition HashMap<>: DEFSTRS.split(" "));
DEFINITIONS.put(definition.substring(0, 2), Integer.parseInt(definition.substring(2)));
for (String p : iso.split(" "))
isoPairs.put(p.substring(0, 2), Integer.parseInt(p.substring(2)));
}
 
public static void main(String[] args) {
for (String iban : new String[]{"GB82 WESTibans 1234= 5698 7654 32",{
"GB82 TESTWEST 1234 5698 7654 32",
"GB81GB82 WESTTEST 1234 5698 7654 32",
"SA03GB81 8000WEST 00001234 60805698 10167654 751932",
"CH93SA03 00768000 20110000 62386080 52951016 77519"}),
System.out.printf("%s is valid: %s%n%n ",CH93 iban,0076 validateIBAN(iban));2011 6238 5295 7",
"XX00 0000",
"",
"DE",
"DE13 äöü_ 1234 1234 1234 12"};
for (String iban : ibans)
System.out.printf("%s is %s.%n", iban, validateIBAN(iban) ? "valid" : "not valid");
}
 
static boolean validateIBAN(String iban) {
iban = iban.replaceAll("\\s", "").toUpperCase(Locale.ROOT);
 
int len = iban.length();
if (len < 4 || !iban.matches("[0-9A-Z]+") || DEFINITIONS.getOrDefault(iban.substring(0, 2), 0) != len)
 
if (len < 4 || isoPairs.get(iban.substring(0, 2)) != len)
return false;
 
Line 1,605 ⟶ 2,473:
BigInteger bigInt = new BigInteger(sb.toString());
 
return bigInt.mod(new BigInteger.valueOf("97")).intValue() == 1;
}
}</langsyntaxhighlight>{{out}}
<pre>GB82 WEST 1234 5698 7654 32 is valid: true.
GB82 TEST 1234 5698 7654 32 is valid:not falsevalid.
GB81 WEST 1234 5698 7654 32 is valid:not falsevalid.
SA03 8000 0000 6080 1016 7519 is valid: true.
CH93 0076 2011 6238 5295 7 is valid: true.
XX00 0000 is not valid.
is not valid.
DE is not valid.
DE13 äöü_ 1234 1234 1234 12 is not valid.</pre>
 
=={{header|JavaScript}}==
<langsyntaxhighlight JavaScriptlang="javascript">var ibanLen = {
NO:15, BE:16, DK:18, FI:18, FO:18, GL:18, NL:18, MK:19,
SI:19, AT:20, BA:20, EE:20, KZ:20, LT:20, LU:20, CR:21,
Line 1,642 ⟶ 2,514:
document.write(isValid('GB82 TEST 1234 5698 7654 32'), '<br>') // false
document.write(isValid('SA03 8000 0000 6080 1016 7519'), '<br>') // true
</syntaxhighlight>
</lang>
{{out}}
true
Line 1,653 ⟶ 2,525:
This implementation requires a version of jq with <tt>gsub</tt>.
 
The heart of the matter consists of just four lines of straightforward jq code:<langsyntaxhighlight lang="jq">
# strip the input string of spaces and tabs:
gsub("[ \t]";"")
Line 1,662 ⟶ 2,534:
# check the mod 97 criterion:
and ( (.[4:] + .[0:4]) | letters2digits | remainder) == 1
</syntaxhighlight>
</lang>
This conciseness is achieved courtesy of the helper functions: <tt>letters2digits</tt> and <tt>remainder</tt>. These could be implemented as inner functions of the main function,
but for clarity they are shown as top-level functions here.
<langsyntaxhighlight lang="jq">def letters2digits:
65 as $A | 90 as $Z
| ($A - 10) as $ten
Line 1,680 ⟶ 2,552:
# output: its remainder modulo 97 as a number
def remainder:
if length < 15 then (.|tonumber) % 97
else (.[0:14] | remainder | tostring) as $r1
| ($r1 + .[14:]) | remainder
Line 1,702 ⟶ 2,574:
and length == $lengths[.[0:2]]
# Shift and convert:
and ( (.[4:] + .[0:4]) | letters2digits | remainder) == 1 ;</langsyntaxhighlight>Examples<syntaxhighlight lang ="jq">
"GB82 WEST 1234 5698 7654 32" | is_valid_iban #=> true
"GB82 TEST 1234 5698 7654 32" | is_valid_iban #=> false</langsyntaxhighlight>
 
=={{header|Jsish}}==
From the Javascript entry.
<syntaxhighlight lang="javascript">var ibanLen = {
NO:15, BE:16, DK:18, FI:18, FO:18, GL:18, NL:18, MK:19,
SI:19, AT:20, BA:20, EE:20, KZ:20, LT:20, LU:20, CR:21,
CH:21, HR:21, LI:21, LV:21, BG:22, BH:22, DE:22, GB:22,
GE:22, IE:22, ME:22, RS:22, AE:23, GI:23, IL:23, AD:24,
CZ:24, ES:24, MD:24, PK:24, RO:24, SA:24, SE:24, SK:24,
VG:24, TN:24, PT:25, IS:26, TR:26, FR:27, GR:27, IT:27,
MC:27, MR:27, SM:27, AL:28, AZ:28, CY:28, DO:28, GT:28,
HU:28, LB:28, PL:28, BR:29, PS:29, KW:30, MU:30, MT:31
};
 
function isIBAN(iban) {
var i,m,s;
iban = iban.replace(/\s/g, '');
if (!iban.match(/^[0-9A-Z]+$/)) return false;
var len = iban.length;
if (len != ibanLen[iban.substr(0,2)]) return false;
iban = iban.substr(4) + iban.substr(0,4);
for (s = '', i = 0; i < len; i += 1) s += parseInt(iban.charAt(i),36);
for (m = s.substr(0, 15) % 97, s = s.substr(15); s; s = s.substr(13)) m = (m + s.substr(0,13)) % 97;
return m == 1;
}
 
;isIBAN('GB82 WEST 1234 5698 7654 32');
;isIBAN('GB82 WEST 1.34 5698 7654 32');
;isIBAN('GB82 WEST 1234 5698 7654 325');
;isIBAN('GB82 TEST 1234 5698 7654 32');
;isIBAN('SA03 8000 0000 6080 1016 7519');
 
/*
=!EXPECTSTART!=
isIBAN('GB82 WEST 1234 5698 7654 32') ==> true
isIBAN('GB82 WEST 1.34 5698 7654 32') ==> false
isIBAN('GB82 WEST 1234 5698 7654 325') ==> false
isIBAN('GB82 TEST 1234 5698 7654 32') ==> false
isIBAN('SA03 8000 0000 6080 1016 7519') ==> true
=!EXPECTEND!=
*/</syntaxhighlight>
 
{{out}}
<pre>prompt$ jsish -u IBAN.jsi
[PASS] IBAN.jsi</pre>
 
=={{header|Julia}}==
{{works with|Julia|0.6}}
 
<syntaxhighlight lang="julia">function validiban(iban::AbstractString)
country2length = Dict(
"AL" => 28, "AD" => 24, "AT" => 20, "AZ" => 28, "BE" => 16, "BH" => 22, "BA" => 20, "BR" => 29,
"BG" => 22, "CR" => 21, "HR" => 21, "CY" => 28, "CZ" => 24, "DK" => 18, "DO" => 28, "EE" => 20,
"FO" => 18, "FI" => 18, "FR" => 27, "GE" => 22, "DE" => 22, "GI" => 23, "GR" => 27, "GL" => 18,
"GT" => 28, "HU" => 28, "IS" => 26, "IE" => 22, "IL" => 23, "IT" => 27, "KZ" => 20, "KW" => 30,
"LV" => 21, "LB" => 28, "LI" => 21, "LT" => 20, "LU" => 20, "MK" => 19, "MT" => 31, "MR" => 27,
"MU" => 30, "MC" => 27, "MD" => 24, "ME" => 22, "NL" => 18, "NO" => 15, "PK" => 24, "PS" => 29,
"PL" => 28, "PT" => 25, "RO" => 24, "SM" => 27, "SA" => 24, "RS" => 22, "SK" => 24, "SI" => 19,
"ES" => 24, "SE" => 24, "CH" => 21, "TN" => 24, "TR" => 26, "AE" => 23, "GB" => 22, "VG" => 24)
 
# Ensure upper alphanumeric input.
iban = replace(iban, r"\s", "")
 
rst = ismatch(r"^[\dA-Z]+$", iban)
# Validate country code against expected length.
rst = rst && length(iban) == country2length[iban[1:2]]
# Shift and convert.
iban = iban[5:end] * iban[1:4]
digs = parse(BigInt, join(parse(Int, ch, 36) for ch in iban))
return rst && digs % 97 == 1
end</syntaxhighlight>
 
{{out}}
<pre>validiban("GB82 WEST 1234 5698 7654 32") = true
validiban("GB82 TEST 1234 5698 7654 32") = false</pre>
 
=={{header|Kotlin}}==
<syntaxhighlight lang="scala">// version 1.0.6
 
import java.math.BigInteger
 
object IBAN {
/* List updated to release 73, January 2017, of IBAN Registry (75 countries) */
private const val countryCodes = "" +
"AD24 AE23 AL28 AT20 AZ28 BA20 BE16 BG22 BH22 BR29 " +
"BY28 CH21 CR22 CY28 CZ24 DE22 DK18 DO28 EE20 ES24 " +
"FI18 FO18 FR27 GB22 GE22 GI23 GL18 GR27 GT28 HR21 " +
"HU28 IE22 IL23 IQ23 IS26 IT27 JO30 KW30 KZ20 LB28 " +
"LC32 LI21 LT20 LU20 LV21 MC27 MD24 ME22 MK19 MR27 " +
"MT31 MU30 NL18 NO15 PK24 PL28 PS29 PT25 QA29 RO24 " +
"RS22 SA24 SC31 SE24 SI19 SK24 SM27 ST25 SV28 TL23 " +
"TN24 TR26 UA29 VG24 XK20"
 
fun isValid(iban: String): Boolean {
// remove spaces from IBAN
var s = iban.replace(" ", "")
 
// check country code and length
s.substring(0, 2) + s.length in countryCodes || return false
 
// move first 4 characters to the end
s = s.substring(4) + s.substring(0, 4)
 
// replace A to Z with numbers 10 To 35
s = s.replace(Regex("[A-Z]")) { (10 + (it.value[0] - 'A')).toString() }
 
// check whether mod 97 calculation gives a remainder of 1
return BigInteger(s) % BigInteger.valueOf(97L) == BigInteger.ONE
}
}
 
fun main() {
val ibans = arrayOf(
"GB82 WEST 1234 5698 7654 32",
"GB82 TEST 1234 5698 7654 32"
)
for (iban in ibans) {
val valid = IBAN.isValid(iban)
println(iban + if (valid) " may be valid" else " is not valid")
}
}</syntaxhighlight>
 
{{out}}
<pre>
GB82 WEST 1234 5698 7654 32 may be valid
GB82 TEST 1234 5698 7654 32 is not valid
</pre>
 
=== With IBAN REGISTRY parser ===
<syntaxhighlight lang="kotlin">
 
package rosettacode
 
import rosettacode.Outcome.Fail
import rosettacode.Outcome.Ok
import java.lang.IllegalArgumentException
import java.math.BigInteger
 
sealed class Outcome {
 
object Ok : Outcome() {
override fun toString(): String = "Ok"
}
 
data class Fail(val error: String) : Outcome()
}
 
fun Boolean.asOutcome(error: String = "") = when (this) {
true -> Ok
false -> Fail(error)
}
 
/**
* A validator based on a pattern (e.g GB2!n4!a6!n8!n) as defined in the IBAN REGISTRY
* Doesn't handle variable length IBANs - sufficient for Rosetta
*
* IBAN REGISTRY: https://www.swift.com/swift_resource/9606
*/
class Validator(private val pattern: String) {
private val triplet: Regex = """(\d+)!([n,a,c])""".toRegex() // e.g: 10!n
private val rules: List<Regex>
 
init {
val countTypePairs = triplet
.findAll(pattern)
.map { Pair(it.groups[1]!!.value.toInt(), it.groups[2]!!.value) }
 
rules = countTypePairs.fold(emptyList()) { acc, p ->
acc + when (p.second) {
"n" -> """[0-9]{${p.first}}""".toRegex()
"a" -> """[A-Z]{${p.first}}""".toRegex()
"c" -> """[A-Z,0-9]{${p.first}}""".toRegex()
else -> throw IllegalArgumentException("Unexpected pattern: $pattern")
}
}
}
 
fun isValid(ccbban: String): Outcome {
var k = 0
 
for (rule in rules) {
when (val match = rule.matchAt(ccbban, k)) {
null -> return Fail("failed rule: $rule")
else -> {
k = match.range.last + 1
}
}
}
return (k == ccbban.length).asOutcome("IBAN is too long")
}
}
 
object Registry : MutableMap<String, Validator> by mutableMapOf()
 
fun String.split(i: Int) = Pair(this.substring(0, i), this.substring(i))
fun String.toDigits() = this.fold("") { acc, ch -> acc + Character.getNumericValue(ch) }
fun Pair<String, String>.swap() = this.second + this.first
 
object CDCheck {
private val _97 = BigInteger.valueOf(97)
private val _1 = BigInteger.ONE
 
operator fun invoke(digits: String) = (BigInteger(digits).mod(_97) == _1).asOutcome("Invalid Check Digits")
}
 
fun validate(iban: String): Outcome {
val normalized = iban.replace(" ", "").uppercase().also {
if (it.length < 5) {
return Fail("IBAN is too short")
}
}
 
val (cc, tail) = normalized.split(2)
val validator = Registry[cc] ?: return Fail("Unknown Country Code: $cc")
 
return when (val outcome = validator.isValid(tail)) {
is Fail -> outcome
is Ok -> {
val allDigits = normalized
.split(4).swap() // (CC + CD) -> end
.toDigits() // letters -> digits
CDCheck(allDigits)
}
}
}
 
fun main() {
Registry["GB"] = Validator("GB2!n4!a6!n8!n")
Registry["DE"] = Validator("DE2!n8!n10!n")
 
validate("GB82WEST12345698765432").also { println(it) } // Ok
validate("GB82 WEST 1234 5698 7654 32").also { println(it) } // Ok
 
validate("DE89370400440532013000").also { println(it) } // Ok
 
validate("XX82WEST1234569A765432").also { println(it) } // Unknown Country Code: XX
validate("GB82").also { println(it) } // IBAN is too short
validate("GB82WEST1234569A765432").also { println(it) } // failed rule: [0-9]{8}
validate("GB82WE5T1234569A765432").also { println(it) } // failed rule: [A-Z]{4}
validate("GB82WEST123456987654329").also { println(it) } // IBAN is too long
validate("GB80WEST12345698765432").also { println(it) } // Invalid Check Digits
}
</syntaxhighlight>
 
{{out}}
<pre>
Ok
Ok
Ok
Fail(error=Unknown Country Code: XX)
Fail(error=IBAN is too short)
Fail(error=failed rule: [0-9]{8})
Fail(error=failed rule: [A-Z]{4})
Fail(error=IBAN is too long)
Fail(error=Invalid Check Digits)
</pre>
 
=={{header|Lobster}}==
<syntaxhighlight lang="lobster">
let cc = ["AD","AE","AL","AO","AT","AZ","BA","BE","BF","BG","BH","BI","BJ","BR","CG","CH","CI","CM","CR","CV","CY",
"CZ","DE","DK","DO","DZ","EE","EG","ES","FI","FO","FR","GA","GB","GE","GI","GL","GR","GT","HR","HU","IE",
"IL","IR","IS","IT","JO","KW","KZ","LB","LI","LT","LU","LV","MC","MD","ME","MG","MK","ML","MR","MT","MU",
"MZ","NL","NO","PK","PL","PS","PT","QA","RO","RS","SA","SE","SI","SK","SM","SN","TN","TR","UA","VG"]
let ln = [ 24, 23, 28, 25, 20, 28, 20, 16, 27, 22, 22, 16, 28, 29, 27, 21, 28, 27, 21, 25, 28,
24, 22, 18, 28, 24, 20, 27, 24, 18, 18, 27, 27, 22, 22, 23, 18, 27, 28, 21, 28, 22,
23, 26, 26, 27, 30, 30, 20, 28, 21, 20, 20, 21, 27, 24, 22, 27, 19, 28, 27, 31, 30,
25, 18, 15, 24, 28, 29, 25, 29, 24, 22, 24, 24, 19, 24, 27, 28, 24, 26, 29, 24 ]
 
def ccToLen(s: string) -> int:
let cnt, idx = binary_search(cc, s.substring(0, 2))
if cnt == 1:
return ln[idx]
else:
return -1
 
def strip(s: string) -> string:
let t = s.tokenize(" ", " ") // splits on spaces and trims spaces from segments
return t.concat_string("") // joins it back together
 
def rotmod97step(accumu: int, c: int) -> int:
accumu *= 10
if '0' <= c and c <= '9':
accumu += c - '0'
else: if 'A' <= c and c <= 'Z':
accumu *= 10
accumu += c + 10 - 'A'
else:
return -1
while accumu >= 97:
accumu -= 97
return accumu
 
def rotmod97(s: string) -> int:
// the first four chars come last
// all chars from 'A' to 'Z' => "10" to "35"
let len = s.length
var accumu = 0 // result; negative indicates error
var i = 4 // starting index
while i < len and accumu >= 0:
accumu = rotmod97step(accumu, s[i])
i += 1
i = 0
while i < 4 and accumu >= 0:
accumu = rotmod97step(accumu, s[i])
i += 1
return accumu
 
def isValidIBAN(iban: string) -> bool:
let s = strip(uppercase(iban))
if s.length == ccToLen(s):
return rotmod97(s) == 1
else:
return false
 
assert isValidIBAN("GB82 WEST 1234 5698 7654 32")
assert isValidIBAN("GB82 West 1234 5698 7654 32")
assert not isValidIBAN("GB82 TEST 1234 5698 7654 32")
assert not isValidIBAN("GB82 WEST 1243 5698 7654 32")
</syntaxhighlight>
 
=={{header|Logtalk}}==
<langsyntaxhighlight lang="logtalk">
:- object(iban).
 
Line 1,837 ⟶ 3,028:
 
:- end_object.
</syntaxhighlight>
</lang>
Testing:
<langsyntaxhighlight lang="logtalk">
| ?- iban::valid("GB82 WEST 1234 5698 7654 32").
yes
</syntaxhighlight>
</lang>
 
=={{header|Lua}}==
<langsyntaxhighlight lang="lua">local length=
{
AL=28, AD=24, AT=20, AZ=28, BH=22, BE=16, BA=20, BR=29, BG=22, CR=21,
Line 1,868 ⟶ 3,059:
end
return mod==1
end</langsyntaxhighlight>
 
=={{header|M2000 Interpreter}}==
We make a lambda function which return a string, with the input IBAN plus (Valid) or (Invalid) at the end.
 
<syntaxhighlight lang="m2000 interpreter">
\\ IBAN checker
Function MakeIBANfun$ {
Inventory countrylength = "AL" := 28, "AD" := 24, "AT" := 20, "AZ" := 28, "BE" := 16, "BH" := 22, "BA" := 20, "BR" := 29
Append countrylength, "BG" := 22, "CR" := 21, "HR" := 21, "CY" := 28, "CZ" := 24, "DK" := 18, "DO" := 28, "EE" := 20
Append countrylength, "FO" := 18, "FI" := 18, "FR" := 27, "GE" := 22, "DE" := 22, "GI" := 23, "GR" := 27, "GL" := 18
Append countrylength, "GT" := 28, "HU" := 28, "IS" := 26, "IE" := 22, "IL" := 23, "IT" := 27, "KZ" := 20, "KW" := 30
Append countrylength, "LV" := 21, "LB" := 28, "LI" := 21, "LT" := 20, "LU" := 20, "MK" := 19, "MT" := 31, "MR" := 27
Append countrylength, "MU" := 30, "MC" := 27, "MD" := 24, "ME" := 22, "NL" := 18, "NO" := 15, "PK" := 24, "PS" := 29
Append countrylength, "PL" := 28, "PT" := 25, "RO" := 24, "SM" := 27, "SA" := 24, "RS" := 22, "SK" := 24, "SI" := 19
Append countrylength, "ES" := 24, "SE" := 24, "CH" := 21, "TN" := 24, "TR" := 26, "AE" := 23, "GB" := 22, "VG" := 24
=Lambda$ countrylength (Iban0$)->{
Iban$=Filter$(Ucase$(Iban0$), " ")
Iban$=Filter$(Iban$, Filter$(Iban$,"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"))
Def Decimal ch, c
{
If Not Exist(countrylength, Left$(Iban$,2)) Then Exit
length=Eval(countrylength)
If Not Len(Iban$)=length Then exit
Buffer ScanChar as Integer*length
Return ScanChar, 0:=Mid$(Iban$,5), length-4:=Mid$(Iban$,1,4)
For i=0 to length-1 {
ch=Eval(ScanChar, i)
if ch>=48 and ch<=57 then {
c = c*10+ch-48
} else.if ch>=65 and ch<=90 then {
c = c*100+ch-55
} else c=-1: exit
}
c = c mod 97
}
=Iban0$ + If$(c=1 ->" (Valid)", " (Invalid)")
}
}
IbanCheck$=MakeIBANfun$()
Print IbanCheck$("GB82 WEST 1234 5698 7654 32") ' valid
Print IbanCheck$("GB82 TEST 1234 5698 7654 32")
Print IbanCheck$("SA03 8000 0000 6080 1016 7519") ' valid
Print IbanCheck$("GR16 0110 1250 0000 0001 2300 695X")
Print IbanCheck$("MK11 2222 3333 4444 555")
</syntaxhighlight>
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<langsyntaxhighlight Mathematicalang="mathematica">CountryCodes={{"AL",28},{"AD",24},{"AT",20},{"AZ",28},{"BE",16},{"BH",22},{"BA",20},{"BR",29},{"BG",22},{"CR",21},{"HR",21},{"CY",28},{"CZ",24},{"DK",18},{"DO",28},{"EE",20},{"FO",18},{"FI",18},{"FR",27},{"GE",22},{"DE",22},{"GI",23},{"GR",27},{"GL",18},{"GT",28},{"HU",28},{"IS",26},{"IE",22},{"IL",23},{"IT",27},{"KZ",20},{"KW",30},{"LV",21},{"LB",28},{"LI",21},{"LT",20},{"LU",20},{"MK",19},{"MT",31},{"MR",27},{"MU",30},{"MC",27},{"MD",24},{"ME",22},{"NL",18},{"NO",15},{"PK",24},{"PS",29},{"PL",28},{"PT",25},{"RO",24},{"SM",27},{"SA",24},{"RS",22},{"SK",24},{"SI",19},{"ES",24},{"SE",24},{"CH",21},{"TN",24},{"TR",26},{"AE",23},{"GB",22},{"VG",24}};
ClearAll[IBANVerify]
IBANVerify[input_String]:=Module[{i,cc,rules},
Line 1,899 ⟶ 3,137:
False
]
]</langsyntaxhighlight>
Trying out the function:
<langsyntaxhighlight Mathematicalang="mathematica">IBANVerify["GB82 WEST 1234 5698 7654 32"]
IBANVerify["GB82 WEST 1234 5698 7654 323"]
IBANVerify["GB82 WEST 1234 5698 7654 31"]
IBANVerify["XX82 WEST 1234 5698 7654 323"]</langsyntaxhighlight>{{out}}
True
False
Line 1,912 ⟶ 3,150:
=={{header|MATLAB}}==
Didn't check country codes, lengths, or consistent checksums to keep this applicable to any new countries.
<langsyntaxhighlight MATLABlang="matlab">function valid = validateIBAN(iban)
% Determine if International Bank Account Number is valid IAW ISO 13616
% iban - string containing account number
Line 1,941 ⟶ 3,179:
i2 = min(i1+8, nDig);
end
end</langsyntaxhighlight>Usage:
<langsyntaxhighlight MATLABlang="matlab">tests = {'GB82 WEST 1234 5698 7654 32' ;
'GB82 TEST 1234 5698 7654 32' ;
'CH93 0076 2011 6238 5295 7' ;
Line 1,952 ⟶ 3,190:
for k = 1:length(tests)
fprintf('%s -> %svalid\n', tests{k}, char(~validateIBAN(tests{k}).*'in'))
end</langsyntaxhighlight>{{out}}
<pre>GB82 WEST 1234 5698 7654 32 -> valid
GB82 TEST 1234 5698 7654 32 -> invalid
Line 1,963 ⟶ 3,201:
 
=={{header|NewLISP}}==
<syntaxhighlight lang="newlisp">
<lang NewLISP>
(setq *iban-code-length* '((15 ("NO"))
(16 ("BE"))
Line 2,031 ⟶ 3,269:
)
)
</syntaxhighlight>
</lang>
Output:
<pre>
Line 2,043 ⟶ 3,281:
=={{header|Nim}}==
{{libheader|bigints}}
<langsyntaxhighlight lang="nim">import tables, strutils, re, bigints
 
let countryLen = toTable({
Line 2,076 ⟶ 3,314:
 
for account in ["GB82 WEST 1234 5698 7654 32", "GB82 TEST 1234 5698 7654 32"]:
echo account, " validation is: ", validIban account</langsyntaxhighlight>{{out}}
GB82 WEST 1234 5698 7654 32 validation is: true
GB82 TEST 1234 5698 7654 32 validation is: false
Line 2,082 ⟶ 3,320:
=={{header|Oberon-2}}==
Works with oo2c Version 2
<langsyntaxhighlight lang="oberon2">
MODULE IBAN;
IMPORT
Line 2,244 ⟶ 3,482:
Test;
END IBAN.
</syntaxhighlight>
</lang>
Output:
<pre>
Line 2,252 ⟶ 3,490:
IBAN[XX0380000000608010167519]=Country XX not has IBAN codes. FALSE
</pre>
 
=={{header|OCaml}}==
{{works with|OCaml|4.03+}}
<syntaxhighlight lang="ocaml">
#load "str.cma"
#load "nums.cma" (* for module Big_int *)
 
 
(* Countries and length of their IBAN. *)
(* Taken from https://en.wikipedia.org/wiki/International_Bank_Account_Number#IBAN_formats_by_country *)
let countries = [
("AL", 28); ("AD", 24); ("AT", 20); ("AZ", 28); ("BH", 22); ("BE", 16);
("BA", 20); ("BR", 29); ("BG", 22); ("CR", 21); ("HR", 21); ("CY", 28);
("CZ", 24); ("DK", 18); ("DO", 28); ("TL", 23); ("EE", 20); ("FO", 18);
("FI", 18); ("FR", 27); ("GE", 22); ("DE", 22); ("GI", 23); ("GR", 27);
("GL", 18); ("GT", 28); ("HU", 28); ("IS", 26); ("IE", 22); ("IL", 23);
("IT", 27); ("JO", 30); ("KZ", 20); ("XK", 20); ("KW", 30); ("LV", 21);
("LB", 28); ("LI", 21); ("LT", 20); ("LU", 20); ("MK", 19); ("MT", 31);
("MR", 27); ("MU", 30); ("MC", 27); ("MD", 24); ("ME", 22); ("NL", 18);
("NO", 15); ("PK", 24); ("PS", 29); ("PL", 28); ("PT", 25); ("QA", 29);
("RO", 24); ("SM", 27); ("SA", 24); ("RS", 22); ("SK", 24); ("SI", 19);
("ES", 24); ("SE", 24); ("CH", 21); ("TN", 24); ("TR", 26); ("AE", 23);
("GB", 22); ("VG", 24); ("DZ", 24); ("AO", 25); ("BJ", 28); ("BF", 27);
("BI", 16); ("CM", 27); ("CV", 25); ("IR", 26); ("CI", 28); ("MG", 27);
("ML", 28); ("MZ", 25); ("SN", 28); ("UA", 29)
]
(* Put the countries in a Hashtbl for faster search... *)
let tbl_countries =
let htbl = Hashtbl.create (List.length countries) in
let _ = List.iter (fun (k, v) -> Hashtbl.add htbl k v) countries in
htbl
 
 
(* Delete spaces and put all letters in upper case. *)
let clean_iban iban =
Str.global_replace (Str.regexp " +") "" iban
|> String.uppercase_ascii
 
 
(* Each country has an IBAN with a specific length. *)
let check_length ib =
let iso_length = List.hd countries |> fst |> String.length in
let country_code = String.sub ib 0 iso_length in
try
Hashtbl.find tbl_countries country_code = String.length ib
with
Not_found -> false
 
 
(* Convert a string into a list of chars. *)
let charlist_of_string s =
let l = String.length s in
let rec doloop i =
if i >= l then []
else s.[i] :: doloop (i + 1)
in
doloop 0
 
 
(* Letters are associated to values: A=10, B=11, ..., Z=35. *)
let val_of_char c =
match c with
| '0' .. '9' -> int_of_char c - int_of_char '0'
| 'A' .. 'Z' -> int_of_char c - int_of_char 'A' + 10
| _ -> failwith (Printf.sprintf "Character not allowed: %c" c)
 
 
(* Compute the mod-97 value and check it is equal to 1. *)
let check_mod97 ib =
let l = String.length ib
and taken = 4 in
let prefix = String.sub ib 0 taken
and rest = String.sub ib taken (l - taken) in
let newval = rest ^ prefix (* move the 4 initial characters to the end of the string *)
|> charlist_of_string (* convert the string into a list of chars *)
|> List.map val_of_char (* convert each char into its integer value *)
|> List.map string_of_int (* convert the integers into strings... *)
|> List.fold_left (^) "" in (* ...and concatenate said strings *)
(* Now compute the mod-97 using the Big Integers provided by OCaml, and
* compare the result to 1. *)
Big_int.eq_big_int
(Big_int.mod_big_int (Big_int.big_int_of_string newval)
(Big_int.big_int_of_int 97))
(Big_int.big_int_of_int 1)
 
 
(* Do the validation as described in the Wikipedia article at
* https://en.wikipedia.org/wiki/International_Bank_Account_Number#Validating_the_IBAN *)
let validate iban =
let ib = clean_iban iban in
check_length ib && check_mod97 ib
 
 
let () =
let ibans = [
("GB82 WEST 1234 5698 7654 32", true);
("GB82 TEST 1234 5698 7654 32", false);
("GB81 WEST 1234 5698 7654 32", false);
("GB82 WEST 1234 5698 7654 3", false);
("SA03 8000 0000 6080 1016 7519", true);
("CH93 0076 2011 6238 5295 7", true);
("\"Completely incorrect iban\"", false)
] in
let testit (ib, exp) =
let res = validate ib in
Printf.printf "%s is %svalid. Expected %b [%s]\n"
ib (if res then "" else "not ")
exp (if res = exp then "PASS" else "FAIL")
in
List.iter (fun pair -> testit pair) ibans
</syntaxhighlight>
{{out}}
GB82 WEST 1234 5698 7654 32 is valid. Expected true [PASS]
GB82 TEST 1234 5698 7654 32 is not valid. Expected false [PASS]
GB81 WEST 1234 5698 7654 32 is not valid. Expected false [PASS]
GB82 WEST 1234 5698 7654 3 is not valid. Expected false [PASS]
SA03 8000 0000 6080 1016 7519 is valid. Expected true [PASS]
CH93 0076 2011 6238 5295 7 is valid. Expected true [PASS]
"Completely incorrect iban" is not valid. Expected false [PASS]
 
=={{header|Perl}}==
<langsyntaxhighlight Perllang="perl">#!/usr/bin/perl
use strict ;
use warnings ;
Line 2,301 ⟶ 3,658:
if ( validate_iban( "GB82TEST12345698765432" ) ) {
print "GB82TEST12345698765432 is valid!\n" ;
}</langsyntaxhighlight>{{out}}
GB82 WEST 1234 5698 7654 32 is a valid IBAN number!
GB82TEST12345698765432 is invalid!
=={{header|Perl 6}}==
<lang perl6>subset IBAN of Str where sub ($_ is copy) {
s:g/\s//;
return False if m/<-[ 0..9 A..Z a..z ]>/ or .chars != <
AD 24 AE 23 AL 28 AT 20 AZ 28 BA 20 BE 16 BG 22 BH 22 BR 29 CH 21
CR 21 CY 28 CZ 24 DE 22 DK 18 DO 28 EE 20 ES 24 FI 18 FO 18 FR 27
GB 22 GE 22 GI 23 GL 18 GR 27 GT 28 HR 21 HU 28 IE 22 IL 23 IS 26
IT 27 KW 30 KZ 20 LB 28 LI 21 LT 20 LU 20 LV 21 MC 27 MD 24 ME 22
MK 19 MR 27 MT 31 MU 30 NL 18 NO 15 PK 24 PL 28 PS 29 PT 25 RO 24
RS 22 SA 24 SE 24 SI 19 SK 24 SM 27 TN 24 TR 26 VG 24
>.hash{.substr(0,2).uc};
s/(.**4)(.+)/$1$0/;
return .subst(:g, /\D/, { :36(~$_) }) % 97 == 1;
}
 
=={{header|Phix}}==
say "$_ is {$_ ~~ IBAN ?? 'valid' !! 'invalid' }" for
<!--<syntaxhighlight lang="phix">(phixonline)-->
'GB82 WEST 1234 5698 7654 32',
<span style="color: #000080;font-style:italic;">--
'gb82 west 1234 5698 7654 32',
-- demo\rosetta\IBAN.exw
'GB82 TEST 1234 5698 7654 32';</lang>{{out}}
-- =====================
GB82 WEST 1234 5698 7654 32 is valid.
--</span>
gb82 west 1234 5698 7654 32 is valid.
<span style="color: #008080;">constant</span> <span style="color: #000000;">nations</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #008000;">"AD"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">24</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- Andorra
GB82 TEST 1234 5698 7654 32 is invalid.
-- (full list in distro)</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"CH"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">21</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- Switzerland</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"GB"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">22</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- United Kingdom</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"SA"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">24</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- Saudi Arabia </span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"XK"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">20</span><span style="color: #0000FF;">}}</span> <span style="color: #000080;font-style:italic;">-- Kosovo</span>
<span style="color: #008080;">constant</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">countries</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lengths</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">columnize</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nations</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">iban</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">code</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- This routine does and should reject codes containing spaces etc.
-- Use iban_s() below for otherwise.</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">country</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">code</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">2</span><span style="color: #0000FF;">],</span><span style="color: #000000;">countries</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">country</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span>
<span style="color: #008080;">and</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">code</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">lengths</span><span style="color: #0000FF;">[</span><span style="color: #000000;">country</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">code</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">code</span><span style="color: #0000FF;">[</span><span style="color: #000000;">5</span><span style="color: #0000FF;">..$]&</span><span style="color: #000000;">code</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">4</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">code</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #000000;">code</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">>=</span><span style="color: #008000;">'0'</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;"><=</span><span style="color: #008000;">'9'</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">*</span><span style="color: #000000;">10</span><span style="color: #0000FF;">+</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">-</span><span style="color: #008000;">'0'</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">>=</span><span style="color: #008000;">'A'</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;"><=</span><span style="color: #008000;">'Z'</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">*</span><span style="color: #000000;">100</span><span style="color: #0000FF;">+</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">-</span><span style="color: #000000;">55</span>
<span style="color: #008080;">else</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">false</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">97</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">false</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">iban_s</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">code</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- strips any embedded spaces and hyphens before validating.</span>
<span style="color: #000000;">code</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute_all</span><span style="color: #0000FF;">(</span><span style="color: #000000;">code</span><span style="color: #0000FF;">,{</span><span style="color: #008000;">" "</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"-"</span><span style="color: #0000FF;">},{</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">iban</span><span style="color: #0000FF;">(</span><span style="color: #000000;">code</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">code</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">bool</span> <span style="color: #000000;">expected</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">valid</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">iban_s</span><span style="color: #0000FF;">(</span><span style="color: #000000;">code</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">state</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">valid</span><span style="color: #0000FF;">=</span><span style="color: #000000;">expected</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">state</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">?</span><span style="color: #008000;">"ok"</span><span style="color: #0000FF;">:</span><span style="color: #008000;">"invalid (as expected)"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">state</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">?</span><span style="color: #008000;">"OK!!"</span><span style="color: #0000FF;">:</span><span style="color: #008000;">"INVALID!!"</span><span style="color: #0000FF;">)&</span><span style="color: #008000;">" (NOT AS EXPECTED)"</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%-34s :%s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">code</span><span style="color: #0000FF;">,</span><span style="color: #000000;">state</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"GB82 WEST 1234 5698 7654 32"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"GB82 TEST 1234 5698 7654 32"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"GB81 WEST 1234 5698 7654 32"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"SA03 8000 0000 6080 1016 7519"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"CH93 0076 2011 6238 5295 7"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
GB82 WEST 1234 5698 7654 32 :ok
GB82 TEST 1234 5698 7654 32 :invalid (as expected)
GB81 WEST 1234 5698 7654 32 :invalid (as expected)
SA03 8000 0000 6080 1016 7519 :ok
CH93 0076 2011 6238 5295 7 :ok
</pre>
 
=={{header|PHP}}==
<langsyntaxhighlight lang="php">
<?php
 
Line 2,410 ⟶ 3,814:
echo "IBAN NOT VALID";
}
</syntaxhighlight>
</lang>
 
=={{header|Picat}}==
<syntaxhighlight lang="picat">go =>
IBAN = "GB82 WEST 1234 5698 7654 32",
println(IBAN=iban(IBAN)),
nl.
 
iban(IBAN) = Ret =>
nations(Nations),
Ret = [],
IBAN2 = IBAN.delete_all(' ').to_uppercase(),
Len = IBAN2.length,
Len > 2, % sanity check
if Len != Nations.get(slice(IBAN2,1,2),0).to_integer() then
Ret := ["wrong country length"]
end,
IBAN3 = slice(IBAN2,5,Len) ++ slice(IBAN2,1,4),
if [convert(C) : C in IBAN3].join('').to_integer() mod 97 != 1 then
Ret := Ret ++ ["bad mod"]
end,
if Ret == [] then Ret := "ok" end.
 
 
% convert char: 1=1,...9=9, A=10, B=11,Z=35
convert(C) = cond(ord(C)-65 >= 0,ord(C)-55,ord(C)-48).to_string().
 
% Lengths for different nations.
nations(Nations) =>
Nations = new_map(
["AL"=28, "AD"=24, "AT"=20, "AZ"=28, "BH"=22, "BE"=16, "BA"=20, "BR"=29, "BG"=22, "CR"=21,
"HR"=21, "CY"=28, "CZ"=24, "DK"=18, "DO"=28, "EE"=20, "FO"=18, "FI"=18, "FR"=27, "GE"=22,
"DE"=22, "GI"=23, "GR"=27, "GL"=18, "GT"=28, "HU"=28, "IS"=26, "IE"=22, "IL"=23, "IT"=27,
"JO"=30, "KZ"=20, "KW"=30, "LV"=21, "LB"=28, "LI"=21, "LT"=20, "LU"=20, "MK"=19, "MT"=31,
"MR"=27, "MU"=30, "MC"=27, "MD"=24, "ME"=22, "NL"=18, "NO"=15, "PK"=24, "PS"=29, "PL"=28,
"PT"=25, "QA"=29, "RO"=24, "SM"=27, "SA"=24, "RS"=22, "SK"=24, "SI"=19, "ES"=24, "SE"=24,
"CH"=21, "TN"=24, "TR"=26, "AE"=23, "GB"=22, "VG"=24]).</syntaxhighlight>
 
{{out}}
<pre>GB82 WEST 1234 5698 7654 32 = ok</pre>
 
===Some more (and interesting) tests===
<syntaxhighlight lang="picat">go2 =>
Ibans = ["GB82 WEST 1234 5698 7654 32",
"gb82 WEST 1234 5698 7654 32",
"GB82WEST12345698765432",
"GB82 WEST 234 5698 7654 32",
"GB82 WEST 1234 5698 7654 33",
"AE82 WEST 1234 5698 7654 32",
 
"GB82 TEST 1234 5698 7654 32",
"GR16 0110 1250 0000 0001 2300 695",
"GB29 NWBK 6016 1331 9268 19",
"SA03 8000 0000 6080 1016 7519",
"CH93 0076 2011 6238 5295 7",
"IL62 0108 0000 0009 9999 999"
],
foreach(IBAN in Ibans)
println(IBAN=iban(IBAN))
end,
nl.</syntaxhighlight>
 
{{out}}
<pre>GB82 WEST 1234 5698 7654 32 = ok
gb82 WEST 1234 5698 7654 32 = ok
GB82WEST12345698765432 = ok
GB82 WEST 234 5698 7654 32 = [wrong country length,bad mod]
GB82 WEST 1234 5698 7654 33 = [bad mod]
AE82 WEST 1234 5698 7654 32 = [wrong country length,bad mod]
GB82 TEST 1234 5698 7654 32 = [bad mod]
GR16 0110 1250 0000 0001 2300 695 = ok
GB29 NWBK 6016 1331 9268 19 = ok
SA03 8000 0000 6080 1016 7519 = ok
CH93 0076 2011 6238 5295 7 = ok
IL62 0108 0000 0009 9999 999 = ok</pre>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight Picolisplang="picolisp">(setq *Sizes '((GB . 22) (CH . 21) (SA . 24)))
 
(de iban (Str)
Line 2,442 ⟶ 3,920:
(println 'Invalid) ) )
 
(bye)</langsyntaxhighlight>
 
=={{header|PowerShell}}==
<syntaxhighlight lang="powershell">
function verifIBAN ([string]$ibanS)
{
if ($ibanS.Length -ne 27) {return $false} else
{
$ibanI="$($ibanS.Substring(4,23))$($ibanS.Substring(0,4))".ToUpper()
[int]$comptIBAN=0
$NumIBAN=""
while ($comptIBAN -lt 27)
{
if ([byte]$ibanI[$comptIBAN] -ge 65 -and [byte]$ibanI[$comptIBAN] -le 90)
{
$NumIban+=([byte]$ibanI[$comptIBAN]-55)
} #pour transformer les lettres en chiffres (A=10, B=11...)
else
{
$NumIban+=$ibanI[$comptIBAN]
}
$comptIBAN++
}
#cela fait un nombre de 30 chiffres : trop pour powershell, je découpe donc les 9 premiers caractères :
if ("$($NumIBAN.Substring(0,9)%97)$($NumIBAN.Substring(9,$NumIBAN.Length-9))"%97 -eq 1)
{return $true}
else
{return $false}
}
} #fin fonction vérification IBAN / Stéphane RABANY 2018
</syntaxhighlight>
 
Ancien texte qui ne sert à rien selon moi :
I have heard that Regex should not be used with IBAN codes. Regex does seem to work, however.
<syntaxhighlight lang="powershell">
<lang PowerShell>
@'
"Country","Length","Example"
Line 2,507 ⟶ 4,015:
 
$ibans
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Line 2,560 ⟶ 4,068:
United Kingdom GB 22 GB29NWBK60161331926819
</pre>
<syntaxhighlight lang="powershell">
<lang PowerShell>
$regex = [regex]'[a-zA-Z]{2}[0-9]{2}[a-zA-Z0-9]{6}[0-9]{5}([a-zA-Z0-9]?){0,16}'
 
Line 2,571 ⟶ 4,079:
}
}
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Line 2,626 ⟶ 4,134:
 
=={{header|PureBasic}}==
<langsyntaxhighlight lang="purebasic">EnableExplicit
Enumeration IBAN
#IBAN_VAL
Line 2,717 ⟶ 4,225:
ForEver
Input()
End</langsyntaxhighlight>
{{out}}
<pre>
Line 2,736 ⟶ 4,244:
=={{header|Python}}==
{{trans|Ruby}}
<langsyntaxhighlight lang="python">import re
 
_country2length = dict(
Line 2,763 ⟶ 4,271:
if __name__ == '__main__':
for account in ["GB82 WEST 1234 5698 7654 32", "GB82 TEST 1234 5698 7654 32"]:
print('%s validation is: %s' % (account, valid_iban(account)))</langsyntaxhighlight>{{out}}
GB82 WEST 1234 5698 7654 32 validation is: True
GB82 TEST 1234 5698 7654 32 validation is: False
 
=={{header|Racket}}==
<langsyntaxhighlight lang="racket">#lang racket
(define lens
'([AL 28] [AD 24] [AT 20] [AZ 28] [BH 22] [BE 16] [BA 20] [BR 29] [BG 22]
Line 2,792 ⟶ 4,300:
 
(valid-iban? "GB82 WEST 1234 5698 7654 32") ; => #t
(valid-iban? "GB82 TEST 1234 5698 7654 32") ; => #f</langsyntaxhighlight>
 
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku" line>subset IBAN of Str where sub ($_ is copy) {
s:g/\s//;
return False if m/<-alnum>/ or .chars != <
AD 24 AE 23 AL 28 AT 20 AZ 28 BA 20 BE 16 BG 22 BH 22 BR 29 CH 21
CR 21 CY 28 CZ 24 DE 22 DK 18 DO 28 EE 20 ES 24 FI 18 FO 18 FR 27
GB 22 GE 22 GI 23 GL 18 GR 27 GT 28 HR 21 HU 28 IE 22 IL 23 IS 26
IT 27 KW 30 KZ 20 LB 28 LI 21 LT 20 LU 20 LV 21 MC 27 MD 24 ME 22
MK 19 MR 27 MT 31 MU 30 NL 18 NO 15 PK 24 PL 28 PS 29 PT 25 RO 24
RS 22 SA 24 SE 24 SI 19 SK 24 SM 27 TN 24 TR 26 VG 24
>.hash{.substr(0,2).uc};
s/(.**4)(.+)/$1$0/;
return .subst(:g, /\D/, { :36(~$_) }) % 97 == 1;
}
 
say "$_ is {$_ ~~ IBAN ?? 'valid' !! 'invalid' }" for
'GB82 WEST 1234 5698 7654 32',
'gb82 west 1234 5698 7654 32',
'GB82 TEST 1234 5698 7654 32';</syntaxhighlight>{{out}}
GB82 WEST 1234 5698 7654 32 is valid.
gb82 west 1234 5698 7654 32 is valid.
GB82 TEST 1234 5698 7654 32 is invalid.
 
=={{header|REXX}}==
These REXX programs can validate an IBAN specified on the command line or from an internal list.
===basic checking===
<langsyntaxhighlight lang="rexx">/*REXX program validates an IBAN (International Bank Account Number). */
@.=; @.1 = @.'GB82 WEST 1234 =5698 7654 32 '
@.12 = 'GB82Gb82 WESTWest 1234 5698 7654 32 '
@.23 = 'Gb82GB82 WestTEST 1234 5698 7654 32 '
@.34 = 'GB82 TEST 1234 5698 7654 32GR16 0110 1250 0000 0001 2300 695 '
@.45 = 'GR16GB29 NWBK 6016 1331 9268 19 0110 1250 0000 0001 2300 695 '
@.56 = 'GB29 NWBK 6016SA03 13318000 92680000 196080 1016 7519 '
@.67 = 'SA03CH93 0076 2011 6238 80005295 00007 6080 1016 7519 '
@.78 = 'CH93 0076 2011IL62 62380108 52950000 70009 9999 999 '
@.89 = 'IL62 -0108 -0000 -0009 -9999 -999 '
@.9 10 = 'IL62-0108-0000-0009-9999-999US12 3456 7890 0987 6543 210 '
@.1011 = 'US12 3456 7890 0987 6543 210GR16 0110 1250 0000 0001 2300 695X '
parse arg @.0 @.11 = 'GR16 0110 1250/*get 0000optional 00011st 2300arg 695Xfrom 'CL*/
parse arg @.0 do k=0 + (arg()==0) while @.k\=='' /*geteither: optional first argument0 or 1 ──► n from C.L.*/
dor k=0+ val_IBAN(arg()==0) while @.k\=='' /*either: 0 or 1 ──► n*/)
r = validateIBAN(@.k)
if r==0 then say ' valid IBAN:' @.k
else say 'invalid IBAN:' @.k " " r
if k==0 then leave /*User specified IBAN? Then we're done*/
end /*k*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*──────────────────────────────────VALIDATEIBAN subroutine───────────────────*/
validateIBANval_IBAN: procedure; arg x; numeric digits 200 /*allow for big #numbers in the IBAN's. */
x=space(x,0); L=length(x) /*elide blanks; determine the length. */
cc = 'AD 24 AE 23 AL 28 AT 20 AZ 28 BA 20 BE 16 BG 22 BH 22 BR 29 CH 21 CR 21 CY 28 CZ 24',
'CR 21 CY 28 CZ 24 DE 22 DK 18 DO 28 EE 20 ES 24 FI 18 FO 18 FR 27 GB 22 GE 22 GI 23 GL 18 GR 27 GT 28',
'GBHR 2221 GEHU 28 IE 22 GIIL 23 GLIS 1826 GRIT 27 GTKW 30 KZ 20 LB 28 HRLI 21 HULT 2820 IELU 2220 ILLV 2321 ISMC 2627',
'ITMD 24 ME 22 MK 19 MR 27 KWMT 3031 KZMU 2030 LBNL 2818 LINO 2115 LTPK 2024 LUPL 2028 LVPS 2129 MCPT 2725 MDRO 24 MERS 22',
'MKSA 1924 MRSE 2724 MTSI 3119 MUSK 3024 NLSM 1827 NOTN 1524 TR 26 PKVG 24' PL 28 PS 29 PT 25/*a ROlist 24',of valid countries. */
@ABC# = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' /*the Latin alphabet and decimal digits*/
'RS 22 SA 24 SE 24 SI 19 SK 24 SM 27 TN 24 TR 26 VG 24' /*country list.*/
cc_=left(x, 2); kk=substr(x, 3, 2) /*get IBAN country code and checkDigits*/
@abc# = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' /*alphabet and decimal digits.*/
cc_c#=leftwordpos(xcc_,2 cc); kk=substr(x,3,2) /*getfind IBANthe country code andindex. checkDigits*/
c#cL=wordposword(cc_,cc, c# + 1) /*find the country code index. /*get the length of the country's IBAN.*/
cLe=word(cc,c#+1) '***error*** invalid IBAN' /*getliteral theused lengthwhen ofdisplaying thean country's IBAN.error*/
if c#==0 then return e 'country code:' cc_
e= '***error!*** invalid IBAN' /*literal used when displaying an error*/
if \datatype(x, 'A') then return e 'character:' substr(x, verify(x, @ABC#), 1)
if c#==0 then return e 'country code:' cc_
if cL\datatype(x,'A')==L then return e 'characterlength:' substr L ' (x,verify(x,@abc#),1should be' cL")"
if cL\y==Lsubstr(x, 5)left(x, 4) then return e 'length:' L /*put four 'digs (shouldin be'front cL")"───► the back.*/
yz=substr(x,5)left(x,4) /*put four digs[↓] in fronttranslate ───►characters the──► back.digits*/
do j=1 for L; _=substr(y, j, 1)
z= /* [↓] translate characters ──► digits*/
if datatype(_, 'U') then z=z || pos(_, @ABC#) + 9 /*if uppercase, then ··· */
do j=1 for L; _=substr(y,j,1)
if datatype(_,'U') then else z=z || pos(_,@abc#)+9
end else z=z || _/*j*/
end /*j*/
 
if z//97==1 then return 0 /*check if correct remainder (modulus).*/
return e 'check digits.'</langsyntaxhighlight>
'''{{out|output''' |text=&nbsp; when using the default input:}}
<pre>
valid IBAN: GB82 WEST 1234 5698 7654 32
valid IBAN: Gb82 West 1234 5698 7654 32
invalid IBAN: GB82 TEST 1234 5698 7654 32 ***error!*** invalid check digits.
valid IBAN: GR16 0110 1250 0000 0001 2300 695
valid IBAN: GB29 NWBK 6016 1331 9268 19
Line 2,854 ⟶ 4,385:
valid IBAN: CH93 0076 2011 6238 5295 7
valid IBAN: IL62 0108 0000 0009 9999 999
invalid IBAN: IL62-0108-0000-0009-9999-999 ***error!*** invalid IBAN character: -
invalid IBAN: US12 3456 7890 0987 6543 210 ***error!*** invalid IBAN country code: US
invalid IBAN: GR16 0110 1250 0000 0001 2300 695X ***error!*** invalid IBAN length: 28 (should be 27)
</pre>
 
Line 2,863 ⟶ 4,394:
:* checks for two countries that may not be valid (as per their entry date into the IBAN system)
:* checks some countries to make sure their check digits match a specific value
<langsyntaxhighlight lang="rexx">/*REXX programpgm validates an IBAN (International Bank Account Number). , including date ranges.*/
@.=; @.1 = @.'GB82 WEST 1234 =5698 7654 32 '
@.12 = 'GB82Gb82 WESTWest 1234 5698 7654 32 '
@.23 = 'Gb82GB82 WestTEST 1234 5698 7654 32 '
@.34 = 'GB82 TEST 1234 5698 7654 32GR16 0110 1250 0000 0001 2300 695 '
@.45 = 'GR16GB29 NWBK 6016 1331 9268 19 0110 1250 0000 0001 2300 695 '
@.56 = 'GB29 NWBK 6016SA03 13318000 92680000 196080 1016 7519 '
@.67 = 'SA03CH93 0076 2011 6238 80005295 00007 6080 1016 7519 '
@.78 = 'CH93 0076 2011IL62 62380108 52950000 70009 9999 999 '
@.89 = 'IL62 -0108 -0000 -0009 -9999 -999 '
@.9 10 = 'IL62-0108-0000-0009-9999-999US12 3456 7890 0987 6543 210 '
@.1011 = 'US12 3456 7890 0987 6543 210GR16 0110 1250 0000 0001 2300 695X '
@.1112 = 'GR16GT11 01102222 12503333 00004444 00015555 23006666 695X7777 '
@.1213 = 'GT11MK11 2222 3333 4444 5555555 6666 7777 '
parse arg @.0 @.13 = 'MK11 2222 3333 4444 555 /*get optional 1st arg from 'CL*/
parse arg @.0 do k=0 + (arg()==0) while @.k\=='' /*geteither: optional first argument0 or 1 ──► n from C.L.*/
dor k=0+ val_IBAN(arg()==0) while @.k\=='' /*either: 0 or 1 ──► n*/)
r = validateIBAN(@.k)
if r==0 then say ' valid IBAN:' @.k
else say 'invalid IBAN:' @.k " " r
if k==0 then leave /*User specified IBAN? Then we're done*/
end /*k*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*──────────────────────────────────VALIDATEIBAN subroutine───────────────────────────────────────*/
validateIBANval_IBAN: procedure; arg x; numeric digits 200 /*allow for big #numbers in the IBAN's. */
x=space(x,0); L=length(x) /*elide blanks; determine the length. */
cc = 'AD 24 AE 23 AL 28 AT 20 AZ 28 BA 20 BE 16 BG 22 BH 22 BR 29 CH 21 CR 21 CY 28 CZ 24',
'CR 21 CY 28 CZ 24 DE 22 DK 18 DO 28 EE 20 ES 24 FI 18 FO 18 FR 27 GB 22 GE 22 GI 23 GL 18 GR 27 GT 28',
'GBHR 2221 GEHU 28 IE 22 GIIL 23 GLIS 1826 GRIT 27 GTKW 30 KZ 20 LB 28 HRLI 21 HULT 2820 IELU 2220 ILLV 2321 ISMC 2627',
'ITMD 24 ME 22 MK 19 MR 27 KWMT 3031 KZMU 2030 LBNL 2818 LINO 2115 LTPK 2024 LUPL 2028 LVPS 2129 MCPT 2725 MDRO 24 MERS 22',
'MKSA 1924 MRSE 2724 MTSI 3119 MUSK 3024 NLSM 1827 NOTN 1524 TR 26 PKVG 24' PL 28 PS 29 PT 25/*a ROlist 24',of valid countries. */
@ABC# = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' /*the Latin alphabet and decimal digits*/
'RS 22 SA 24 SE 24 SI 19 SK 24 SM 27 TN 24 TR 26 VG 24' /*country list.*/
cc_=left(x, 2); kk=substr(x, 3, 2) /*get IBAN country code and checkDigits*/
@abc# = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' /*alphabet and decimal digits.*/
cc_c#=leftwordpos(xcc_,2 cc); kk=substr(x,3,2) /*getfind IBANthe country code andindex. checkDigits*/
c#cL=wordposword(cc_,cc, c# + 1) /*find the country code index. /*get the length of the country's IBAN.*/
cLe=word(cc,c#+1) '***error*** invalid IBAN' /*getliteral theused lengthwhen ofdisplaying thean country's IBAN.error*/
if c#==0 then return e 'country code:' cc_
e= '***error!*** invalid IBAN' /*literal used when displaying an error*/
if c#==0 \datatype(x, 'A') then return e 'country code'character:' cc_substr(x, verify(x, @ABC#), 1)
if cL\datatype(x,'A') ==L then return e 'characterlength:' substr L ' (x,verify(x,@abc#),1should be' cL")"
if cL\==L then return e 'length:' L ' (should be' cL")"
if cc_=='BR' & date("S")<20130701 then return e "country, Brazil isn't valid until 1-July-2013."
if cc_=='GT' & date("S")<20140701 then return e "country, Guatemala isn't valid until 1-July-2014."
Line 2,910 ⟶ 4,439:
if cc_=='PT' & kk\==50 then return e "check digits for Portugal:" kk
if cc_=='SI' & kk\==56 then return e "check digits for Slovenia:" kk
y=substr(x, 5)left(x, 4) /*put four digs in front ───► the back.*/
z= /* [↓] translate characters ──► digits*/
do j=1 for L; _=substr(y, j, 1)
if datatype(_, 'U') then z=z || pos(_, @abcABC#) + 9 /*if uppercase, then ··· */
else z=z || _
end /*j*/
 
if z//97==1 then return 0 /*check if correct remainder (modulus).*/
return e 'check digits.'</langsyntaxhighlight>
'''{{out|output''' |text=&nbsp; when using the default input, &nbsp; (the run date of this program is &nbsp; 29-April-2013):}}
<pre>
valid IBAN: GB82 WEST 1234 5698 7654 32
valid IBAN: Gb82 West 1234 5698 7654 32
invalid IBAN: GB82 TEST 1234 5698 7654 32 ***error!*** invalid IBAN check digits.
valid IBAN: GR16 0110 1250 0000 0001 2300 695
valid IBAN: GB29 NWBK 6016 1331 9268 19
Line 2,929 ⟶ 4,458:
valid IBAN: CH93 0076 2011 6238 5295 7
valid IBAN: IL62 0108 0000 0009 9999 999
invalid IBAN: IL62-0108-0000-0009-9999-999 ***error!*** invalid IBAN character: -
invalid IBAN: US12 3456 7890 0987 6543 210 ***error!*** invalid IBAN country code: US
invalid IBAN: GR16 0110 1250 0000 0001 2300 695X ***error!*** invalid IBAN length: 28 (should be 27)
invalid IBAN: GT11 2222 3333 4444 5555 6666 7777 ***error!*** invalid IBAN country, Guatemala isn't valid until 1-July-2014.
invalid IBAN: MK11 2222 3333 4444 555 ***error!*** invalid IBAN check digits for Macedonia: 11
</pre>
 
=={{header|Ring}}==
<syntaxhighlight lang="ring">
# Project : IBAN
 
codes = list(5)
codes[1] = "GB82 WEST 1234 5698 7654 32"
codes[2] = "GB82 TEST 1234 5698 7654 32"
codes[3] = "GB81 WEST 1234 5698 7654 32"
codes[4] = "SA03 8000 0000 6080 1016 7519"
codes[5] = "CH93 0076 2011 6238 5295 7"
 
for y = 1 to len(codes)
see codes[y]
flag = 1
codes[y] = substr(codes[y], " ", "")
checkcode(codes[y])
check = checkiban(codes[y])
if check = 1
see " is valid" + nl
else
see " is invalid" + nl
ok
next
 
func checkcode(code)
for n = 1 to 2
if ascii(code[n]) < 65 or ascii(code[n]) > 90
flag = 0
ok
next
for m = 3 to len(code)
if (ascii(code[m]) > 64 and ascii(code[m]) < 91) or (ascii(code[m]) > 47 and ascii(code[m]) < 58)
else
flag = 0
ok
next
 
func checkiban(code)
code= substr(code, 5, len(code) - 4) + left(code, 4)
for x = 1 to len(code)
if ascii(code[x]) > 64 and ascii(code[x]) < 91
code = left(code, x-1) + string(ascii(code[x]) - 55) + right(code, len(code) - x)
ok
next
modold = left(code,9) % 97
for p = 1 to floor((len(code)-9)/7)
modnew = string(modold) + substr(code, 10 + (p-1) * 7, 7)
modnew = number(modnew) % 97
modold = modnew
next
modrest = right(code, len(code) - ((p-1)*7 + 9))
modnew = string(modold) + modrest
modnew = number(modnew) % 97
return modnew
</syntaxhighlight>
Output:
<pre>
GB82 WEST 1234 5698 7654 32 is valid
GB82 TEST 1234 5698 7654 32 is invalid
GB81 WEST 1234 5698 7654 32 is invalid
SA03 8000 0000 6080 1016 7519 is valid
CH93 0076 2011 6238 5295 7 is valid
</pre>
 
=={{header|Ruby}}==
{{works with|Ruby|1.9+}}
<langsyntaxhighlight Rubylang="ruby">def valid_iban? iban
len = {
AL: 28, AD: 24, AT: 20, AZ: 28, BE: 16, BH: 22, BA: 20, BR: 29,
Line 2,966 ⟶ 4,559:
 
p valid_iban? "GB82 WEST 1234 5698 7654 32" #=> true
p valid_iban? "GB82 TEST 1234 5698 7654 32" #=> false</langsyntaxhighlight>
 
=={{header|Rust}}==
<syntaxhighlight lang="rust">
fn main() {
for iban in [
"",
"x",
"QQ82",
"QQ82W",
"GB82 TEST 1234 5698 7654 322",
"gb82 WEST 1234 5698 7654 32",
"GB82 WEST 1234 5698 7654 32",
"GB82 TEST 1234 5698 7654 32",
"GB81 WEST 1234 5698 7654 32",
"SA03 8000 0000 6080 1016 7519",
"CH93 0076 2011 6238 5295 7",
].iter()
{
println!(
"'{}' is {}valid",
iban,
if validate_iban(iban) { "" } else { "NOT " }
);
}
}
 
fn validate_iban(iban: &str) -> bool {
let iso_len = [
("AL", 28), ("AD", 24), ("AT", 20), ("AZ", 28), ("BE", 16), ("BH", 22),
("BA", 20), ("BR", 29), ("BG", 22), ("HR", 21), ("CY", 28), ("CZ", 24),
("DK", 18), ("DO", 28), ("EE", 20), ("FO", 18), ("FI", 18), ("FR", 27),
("GE", 22), ("DE", 22), ("GI", 23), ("GL", 18), ("GT", 28), ("HU", 28),
("IS", 26), ("IE", 22), ("IL", 23), ("IT", 27), ("KZ", 20), ("KW", 30),
("LV", 21), ("LB", 28), ("LI", 21), ("LT", 20), ("LU", 20), ("MK", 19),
("MT", 31), ("MR", 27), ("MU", 30), ("MC", 27), ("MD", 24), ("ME", 22),
("NL", 18), ("NO", 15), ("PK", 24), ("PS", 29), ("PL", 28), ("PT", 25),
("RO", 24), ("SM", 27), ("SA", 24), ("RS", 22), ("SK", 24), ("SI", 19),
("ES", 24), ("SE", 24), ("CH", 21), ("TN", 24), ("TR", 26), ("AE", 23),
("GB", 22), ("VG", 24), ("GR", 27), ("CR", 21),
];
let trimmed_iban = iban.chars()
.filter(|&ch| ch != ' ')
.collect::<String>()
.to_uppercase();
if trimmed_iban.len() < 4 {
return false;
}
let prefix = &trimmed_iban[0..2];
if let Some(pair) = iso_len.iter().find(|&&(code, _)| code == prefix) {
if pair.1 != trimmed_iban.len() {
return false;
}
} else {
return false;
}
let reversed_iban = format!("{}{}", &trimmed_iban[4..], &trimmed_iban[0..4]);
let mut expanded_iban = String::new();
for ch in reversed_iban.chars() {
expanded_iban.push_str(&if ch.is_numeric() {
format!("{}", ch)
} else {
format!("{}", ch as u8 - 'A' as u8 + 10u8)
});
}
expanded_iban.bytes().fold(0, |acc, ch| {
(acc * 10 + ch as u32 - '0' as u32) % 97
}) == 1
}
</syntaxhighlight>
 
=={{header|Scala}}==
{{libheader|Scala}}<langsyntaxhighlight Scalalang="scala">import scala.collection.immutable.SortedMap
 
class Iban(val iban: String) {
Line 3,010 ⟶ 4,672:
map(v => (v.take(2), if (v.isEmpty) 0 else v.slice(2, 4).toInt))
 
lazy val pattern = "([A-Z]{2})([0-9]{2})([A-Z0-9]{4})([A-Z0-9]{0,2})([0-9]{7})(([A-Z0-9]?){0,1630})".r
 
def apply(s: String) = new Iban(s.replaceAll( """\s""", ""))
}</langsyntaxhighlight>The test program:
<langsyntaxhighlight Scalalang="scala">object IbanTest extends App {
def blackCases = """AT611904300235473201
|GB82TEST12345698765432
Line 3,111 ⟶ 4,773:
blackCases.lines.foreach(l => assert(!Iban(l).isValidIban))
println(s"Successfully completed; ${whiteCases.lines.size + blackCases.lines.size} cases tested, no errors.")
}</langsyntaxhighlight>
{{out}}
Successfully completed; 91 cases tested, no errors.
 
=={{header|Seed7}}==
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
include "bigint.s7i";
 
Line 3,172 ⟶ 4,834:
check("GB82 TEST 1234 5698 7654 32");
check("GB82 WEST 1243 5698 7654 32");
end func;</langsyntaxhighlight>
{{out}}
<pre>
Line 3,183 ⟶ 4,845:
 
=={{header|Sidef}}==
<langsyntaxhighlight lang="ruby">func valid_iban(iban) {
static len = Hash.new(
AD=>24, AE=>23, AL=>28, AO=>25, AT=>20, AZ=>28, BA=>20, BE=>16, BF=>27,
BG=>22, BH=>22, BI=>16, BJ=>28, BR=>29, CG=>27, CH=>21, CI=>28, CM=>27,
Line 3,195 ⟶ 4,857:
RS=>22, SA=>24, SE=>24, SI=>19, SK=>24, SM=>27, SN=>28, TN=>24, TR=>26,
UA=>29, VG=>24,
);
 
# Ensure upper alphanumeric input.
iban -= /\s+/g;
iban.uc! ~~ /^[0-9A-Z]+\z/ || return false;
 
# Validate country code against expected length.
var cc = iban.substr(0, 2);
iban.len == len{cc} || return false;
 
# Shift and convert.
iban.sub!(/(.{4})(.+)/, {|a,b| b+a});
iban.gsub!(/([A-Z])/, {|a| a.ord - 55});
 
iban.to_i % 97 == 1;
}
 
say valid_iban("GB82 WEST 1234 5698 7654 32"); #=> true
say valid_iban("GB82 TEST 1234 5698 7654 32"); #=> false</langsyntaxhighlight>
 
=={{header|SNOBOL4}}==
<langsyntaxhighlight SNOBOL4lang="snobol4">* IBAN - International Bank Account Number validation
DEFINE('ibantable()') :(iban_table_end)
ibantable
Line 3,296 ⟶ 4,958:
 
OUTPUT = "valid IBAN: " line :(read)
END</langsyntaxhighlight>
 
'''Output:'''
Line 3,312 ⟶ 4,974:
Invalid IBAN: IL62-0108-0000-0009-9999-999: length: 28 not 23
Invalid IBAN: GR16 0110 1250 0000 0001 2300 695X: length: 28 not 27</pre>
 
=={{header|Standard ML}}==
{{works with|SML/NJ}}
 
<syntaxhighlight lang="sml">(* country_code : string -> int *)
(* Get the length of a valid IBAN given the two chars long country code *)
fun country_code (str : string) : int =
case str of
"AL" => 28 | "AD" => 24 | "AT" => 20 | "AZ" => 28
| "BE" => 16 | "BH" => 22 | "BA" => 20 | "BR" => 29
| "BG" => 22 | "CR" => 21 | "HR" => 21 | "CY" => 28
| "CZ" => 24 | "DK" => 18 | "DO" => 28 | "EE" => 20
| "FO" => 18 | "FI" => 18 | "FR" => 27 | "GE" => 22
| "DE" => 22 | "GI" => 23 | "GR" => 27 | "GL" => 18
| "GT" => 28 | "HU" => 28 | "IS" => 26 | "IE" => 22
| "IL" => 23 | "IT" => 27 | "KZ" => 20 | "KW" => 30
| "LV" => 21 | "LB" => 28 | "LI" => 21 | "LT" => 20
| "LU" => 20 | "MK" => 19 | "MT" => 31 | "MR" => 27
| "MU" => 30 | "MC" => 27 | "MD" => 24 | "ME" => 22
| "NL" => 18 | "NO" => 15 | "PK" => 24 | "PS" => 29
| "PL" => 28 | "PT" => 25 | "RO" => 24 | "SM" => 27
| "SA" => 24 | "RS" => 22 | "SK" => 24 | "SI" => 19
| "ES" => 24 | "SE" => 24 | "CH" => 21 | "TN" => 24
| "TR" => 26 | "AE" => 23 | "GB" => 22 | "VG" => 24
| _ => raise Domain
 
 
(* removespace : string -> string *)
(* Removes all spaces from a string *)
fun removespace s = String.translate (fn #" " => "" | c => str c) s
 
(* to_upper : string -> string *)
(* Convert every char to upper of a string *)
fun to_upper (s : string) : string =
String.translate (fn c => str (Char.toUpper c)) s
 
(* convert_to_number : char -> string *)
(* Covert a alphanumeric char into a numerical string *)
fun convert_to_number (c : char) : string =
if Char.isDigit c then str c else
if Char.isUpper c then Int.toString (10 + ord c - ord #"A") else
raise Domain
 
 
(* verify_iban : string -> bool *)
(* Check weather a string is a valid IBAN *)
fun verify_iban str =
let
(* Remove spaces and make upper case *)
val str = to_upper (removespace str)
(* Fetch first two chars (country code) *)
val country = String.substring (str, 0, 2)
val len = country_code country
in
(* size test *)
String.size str = len
andalso
(* Every char must be alphanumeric *)
List.all Char.isAlphaNum (explode str)
andalso
let
(* Reorder *)
val str = String.substring (str, 4, String.size str - 4) ^ String.substring (str, 0, 4)
(* Convert into digits *)
val str = String.translate convert_to_number str
(* Convert into a big number *)
val number = valOf (IntInf.fromString str)
in
IntInf.mod (number, 97) = 1
end
end handle Subscript => false | Domain => false</syntaxhighlight>
 
{{output}}
<pre>- verify_iban "GB82 WEST 1234 5698 7654 32";
val it = true : bool
- verify_iban "GB82 TEST 1234 5698 7654 32";
val it = false : bool</pre>
 
=={{header|Tcl}}==
<langsyntaxhighlight lang="tcl">proc verifyIBAN {iban} {
# Normalize by up-casing and stripping illegal chars (e.g., space)
set iban [regsub -all {[^A-Z0-9]+} [string toupper $iban] ""]
Line 3,347 ⟶ 5,086:
# Verify length and modulus
return [expr {[string length $iban] == $len && $num % 97 == 1}]
}</langsyntaxhighlight>Demonstrating:
<langsyntaxhighlight lang="tcl">set iban "GB82 WEST 1234 5698 7654 32"
puts "$iban is [expr {[verifyIBAN $iban] ? {verified} : {unverified}}]"
set not "GB42 WEST 1234 5698 7654 32"
puts "$not is [expr {[verifyIBAN $not] ? {verified} : {unverified}}]"</langsyntaxhighlight>{{out}}
<pre>GB82 WEST 1234 5698 7654 32 is verified
GB42 WEST 1234 5698 7654 32 is unverified</pre>
Line 3,358 ⟶ 5,097:
{{works with|bash}}
This does not verify the country code or the length.
<langsyntaxhighlight lang="bash">declare -A base36=(
[A]=10 [B]=11 [C]=12 [D]=13 [E]=14 [F]=15 [G]=16 [H]=17 [I]=18
[J]=19 [K]=20 [L]=21 [M]=22 [N]=23 [O]=24 [P]=25 [Q]=26 [R]=27
Line 3,391 ⟶ 5,130:
printf "%s : " "$test"
is_iban "$test" && echo yes || echo no
done</langsyntaxhighlight>
 
{{output}}
<pre>GB82 WEST 1234 5698 7654 32 : yes
GB42 WEST 1234 5698 7654 32 : no</pre>
 
=={{header|VBA}}==
{{trans|Phix}}<syntaxhighlight lang="vb">Public nations As New Collection
Private Sub init()
nations.Add 24, "AD"
nations.Add 21, "CH"
nations.Add 22, "GB"
nations.Add 24, "SA"
nations.Add 20, "XK"
End Sub
 
Private Function mod97(ByVal c As String) As Integer
Dim n As Long
n = Val(Mid(c, 1, 9))
c = Mid(c, 10, Len(c) - 9)
n = n Mod 97
Do While Len(c) > 6
n = Val(Str(n) & Mid(c, 1, 7))
n = n Mod 97
c = Mid(c, 8, Len(c) - 7)
Loop
n = Val(Str(n) & c)
mod97 = n Mod 97
End Function
 
Private Function iban(ByVal code As String) As Boolean
'-- This routine does and should reject codes containing spaces etc.
'-- Use iban_s() below for otherwise.
On Error GoTo 1
lengths = nations(Mid(code, 1, 2))
If Len(code) = lengths Then
code = code & Mid(code, 1, 4)
code = Mid(code, 5, lengths)
Dim c As String: c = ""
Dim ch As String
For i = 1 To lengths
ch = Mid(code, i, 1)
If ch >= "0" And ch <= "9" Then
c = c & ch
Else
If ch >= "A" And ch <= "Z" Then
c = c & Str(Asc(ch) - 55)
Else
iban = False
End If
End If
Next i
c = Replace(c, " ", "")
iban = mod97(c) = 1
End If
Exit Function
1:
iban = False
End Function
Private Function iban_s(code As String) As Boolean
'-- strips any embedded spaces and hyphens before validating.
code = Replace(code, " ", "")
code = Replace(code, "-", "")
iban_s = iban(code)
End Function
Private Sub test(code As String, expected As Boolean)
Dim valid As Boolean
valid = iban_s(code)
Dim state As String
If valid = expected Then
state = IIf(valid, "ok", "invalid (as expected)")
Else
state = IIf(valid, "OK!!", "INVALID!!") & " (NOT AS EXPECTED)"
End If
Debug.Print code, state
End Sub
 
Public Sub main()
init
test "GB82 WEST 1234 5698 7654 32", True
test "GB82 TEST 1234 5698 7654 32", False
test "GB81 WEST 1234 5698 7654 32", False
test "SA03 8000 0000 6080 1016 7519", True
test "CH93 0076 2011 6238 5295 7", True
End Sub</syntaxhighlight>{{out}}
<pre>GB82WEST12345698765432 ok
GB82TEST12345698765432 invalid (as expected)
GB81WEST12345698765432 invalid (as expected)
SA0380000000608010167519 ok
CH9300762011623852957 ok</pre>
 
=={{header|VBScript}}==
<syntaxhighlight lang="vb">
<lang vb>
Function validate_iban(s)
validate_iban = Chr(34) & s & Chr(34) & " is NOT valid."
Line 3,457 ⟶ 5,283:
WScript.StdOut.WriteLine validate_iban("US12 3456 7890 0987 6543 210")
WScript.StdOut.WriteLine validate_iban("GR16 0110 1250 0000 0001 2300 695X")
</syntaxhighlight>
</lang>
 
{{Out}}
Line 3,474 ⟶ 5,300:
"GR16 0110 1250 0000 0001 2300 695X" is NOT valid.
</pre>
 
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|Wren-big}}
<syntaxhighlight lang="wren">import "./big" for BigInt
 
var countryCodes =
"AD24 AE23 AL28 AT20 AZ28 BA20 BE16 BG22 BH22 BR29 " +
"BY28 CH21 CR22 CY28 CZ24 DE22 DK18 DO28 EE20 ES24 " +
"FI18 FO18 FR27 GB22 GE22 GI23 GL18 GR27 GT28 HR21 " +
"HU28 IE22 IL23 IQ23 IS26 IT27 JO30 KW30 KZ20 LB28 " +
"LC32 LI21 LT20 LU20 LV21 MC27 MD24 ME22 MK19 MR27 " +
"MT31 MU30 NL18 NO15 PK24 PL28 PS29 PT25 QA29 RO24 " +
"RS22 SA24 SC31 SE24 SI19 SK24 SM27 ST25 SV28 TL23 " +
"TN24 TR26 UA29 VG24 XK20"
 
var isValid = Fn.new { |iban|
// remove spaces from IBAN
var s = iban.replace(" ", "")
 
// check country code and length
if (!countryCodes.contains(s[0..1] + s.count.toString)) return false
 
// move first 4 characters to the end
s = s[4..-1] + s[0..3]
 
// replace A to Z with numbers 10 To 35
var i = 10
for (c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ") {
s = s.replace(c, i.toString)
i = i + 1
}
 
// check whether mod 97 calculation gives a remainder of 1
return (BigInt.new(s) % BigInt.new(97)) == BigInt.one
}
 
var ibans = [ "GB82 WEST 1234 5698 7654 32", "GB82 TEST 1234 5698 7654 32" ]
for (iban in ibans) {
var valid = isValid.call(iban)
System.print(iban + (valid ? " may be valid" : " is not valid"))
}</syntaxhighlight>
 
{{out}}
<pre>
GB82 WEST 1234 5698 7654 32 may be valid
GB82 TEST 1234 5698 7654 32 is not valid
</pre>
 
=={{header|Yabasic}}==
{{trans|Phix}}
<syntaxhighlight lang="yabasic">// List updated to release 72, 25 November 2016, of IBAN Registry (75 countries)
countryCodes$ = "AD24 AE23 AL28 AT20 AZ28 BA20 BE16 BG22 BH22 BR29 BY28 CH21 CR22 CY28 CZ24 DE22 "
countryCodes$ = countryCodes$ + "DK18 DO28 EE20 ES24 FI18 FO18 FR27 GB22 GE22 GI23 GL18 GR27 GT28 HR21 HU28 IE22 "
countryCodes$ = countryCodes$ + "IL23 IQ23 IS26 IT27 JO30 KW30 KZ20 LB28 LC32 LI21 LT20 LU20 LV21 MC27 MD24 ME22 "
countryCodes$ = countryCodes$ + "MK19 MR27 MT31 MU30 NL18 NO15 PK24 PL28 PS29 PT25 QA29 RO24 RS22 SA24 SC31 SE24 "
countryCodes$ = countryCodes$ + "SI19 SK24 SM27 ST25 SV28 TL23 TN24 TR26 UA29 VG24 XK20"
sub iban(code$)
// This routine does and should reject codes containing spaces etc.
// Use iban_s() below for otherwise.
local country, lcode, c, i, ch$
lcode = len(code$)
country = instr(countryCodes$, upper$(left$(code$, 2)))
if country and lcode = val(mid$(countryCodes$, country + 2, 2)) then
code$ = right$(code$, lcode - 4) + left$(code$, 4)
for i = 1 to lcode
ch$ = mid$(code$, i, 1)
if ch$ >= "0" and ch$ <= "9" then
c = c * 10 + asc(ch$) - asc("0")
elsif ch$ >= "A" and ch$ <= "Z" then
c = c * 100 + asc(ch$) - 55
else
return false
end if
c = mod(c, 97)
next i
return c = 1
end if
return false
end sub
 
sub iban_s(code$)
// strips any embedded spaces and hyphens before validating.
local i, t$(1), n
i = token(code$, t$(), " -")
code$ = ""
for n = 1 to i
code$ = code$ + t$(n)
next n
return iban(code$)
end sub
sub test(code$, expected)
local valid, state$
valid = iban_s(code$)
if valid = expected then
if valid then
state$ = "ok"
else
state$ = "invalid (as expected)"
end if
else
if valid then
state$ = "OK!!"
else
state$ = "INVALID!!"
end if
state$ = state$ + " (NOT AS EXPECTED)"
end if
print code$, "\t ", state$
end sub
test("GB82 WEST 1234 5698 7654 32", true)
test("GB82 TEST 1234 5698 7654 32", false)
test("GB81 WEST 1234 5698 7654 32", false)
test("SA03 8000 0000 6080 1016 7519", true)
test("CH93 0076 2011 6238 5295 7", true)</syntaxhighlight>
 
=={{header|zkl}}==
Using GMP big nums:
<langsyntaxhighlight lang="zkl">var BN=Import("zklBigNum");
fcn validateIBAN(iban){
iban=iban-" \t";
alphaNums.matches(iban) and (ibans.find(iban[0,2])==iban.len()) and
( BN((iban[4,*]+iban[0,4]).apply("toInt",36)) % 97 == 1 )
}</langsyntaxhighlight>Without using big nums:
<langsyntaxhighlight lang="zkl">fcn validateIBAN(iban){
iban=iban-" \t";
alphaNums.matches(iban) and (ibans.find(iban[0,2])==iban.len()) and
Line 3,494 ⟶ 5,444:
}
M
}</langsyntaxhighlight><syntaxhighlight lang ="zkl">var alphaNums=RegExp("^[0-9A-Z]+$");
var ibans= // Dictionary("AD":24, ...)
("AD24 AE23 AL28 AO25 AT20 AZ28 BA20 BE16 BF27 BG22 BH22 BI16 "
Line 3,503 ⟶ 5,453:
"MR27 MT31 MU30 MZ25 NL18 NO15 PK24 PL28 PS29 PT25 QA29 RO24 "
"RS22 SA24 SE24 SI19 SK24 SM27 SN28 TN24 TR26 UA29 VG24")
.split(" ").pump(D(),fcn(w){return(w[0,2],w[2,*].toInt())});</langsyntaxhighlight>Testing 1 2 3
<langsyntaxhighlight lang="zkl"> // all valid
T("GB82 WEST 1234 5698 7654 32","GB82WEST12345698765432",
"GR16 0110 1250 0000 0001 2300 695","GB29 NWBK 6016 1331 9268 19",
Line 3,523 ⟶ 5,473:
...
"CH9300762011623852957").split()
.apply(validateIBAN).toString(*).println();</langsyntaxhighlight>
{{out}}
<pre>
Line 3,536 ⟶ 5,486:
True,True,True,True,True,True,True,True,True,True,True,True)
</pre>
 
=={{header|ZX Spectrum Basic}}==
{{trans|BBC BASIC}}
<syntaxhighlight lang="zxbasic">10 REM REM Used the following as official standard:
20 REM REM http://www.cnb.cz/cs/platebni_styk/iban/download/EBS204.pdf
30 REM REM Pairs of ISO 3166 country code & expected IBAN length for this country
40 LET c$="AL28 AD24 AT20 AZ28 BE16 BH22 BA20 BR29 BG22 CR21 HR21 CY28 CZ24 DK18 DO28 EE20 "
50 LET c$=c$+"FO18 FI18 FR27 GE22 DE22 GI23 GR27 GL18 GT28 HU28 IS26 IE22 IL23 IT27 KZ20 KW30 "
60 LET c$=c$+"LV21 LB28 LI21 LT20 LU20 MK19 MT31 MR27 MU30 MC27 MD24 ME22 NL18 NO15 PK24 PS29 "
70 LET c$=c$+"PL28 PT25 RO24 SM27 SA24 RS22 SK24 SI19 ES24 SE24 CH21 TN24 TR26 AE23 GB22 VG24 "
80 LET e$=""
100 LET i$="GB82 WEST 1234 5698 7654 32": GO SUB 1000
110 LET i$="gb82 west 1234 5698 7654 32": GO SUB 1000
120 LET i$="GB82 TEST 1234 5698 7654 32": GO SUB 1000
130 LET i$="GR16 0110 1250 0000 0001 2300 695": GO SUB 1000
140 LET i$="IL62-0108-0000-0009-9999-999": GO SUB 1000
900 STOP
1000 REM IBAN check routine
1010 LET explen=0: LET lenc=LEN c$
1020 FOR i=1 TO lenc STEP 5
1030 IF i$( TO 2)=c$(i TO i+1) THEN LET explen=VAL c$(i+2 TO i+3): GO TO 2000
1040 NEXT i
2000 LET match=explen>0
2010 REM Continue if country code found
2020 IF NOT match THEN LET e$="country code: "+i$( TO 2): GO TO 3000
2030 REM Remove espace = convert to digital IBAN
2040 LET d$=""
2050 FOR i=1 TO LEN i$
2060 IF i$(i)>" " THEN LET d$=d$+i$(i)
2070 NEXT i
2080 LET match=explen=LEN d$
2090 REM Continue if length is correct
2100 IF NOT match THEN LET e$="code length, expected length: "+STR$ explen: GO TO 3000
2110 REM Create temporary string with country code appended
2120 LET t$=d$(5 TO )+d$(1 TO 2)
2130 REM Make big number, replacing letters by numbers using next conversion table: A=10 ... Z=35
2140 LET b$=""
2150 FOR i=1 TO LEN t$
2160 LET c= CODE t$(i)
2170 IF (c>64 AND c<91) THEN LET b$=b$+STR$ (c-55): GO TO 2200
2190 IF (c>47 AND c<58) THEN LET b$=b$+t$(i)
2200 NEXT i
2210 REM MOD 97 on bignum$+"00" and subtract result from 98 to obtain control number
2220 LET k$=b$+"00": GO SUB 4000
2230 LET kk=98-mod97
2240 REM Compare with control number in IBAN
2250 LET match=VAL i$(3 TO 4)=kk
2260 REM Continue if control number matches
2270 IF NOT match THEN LET e$="check digits, should be: "+STR$ kk: GO TO 3000
2280 REM Append kk to bignum$ and determine if MOD 97 results in 1
2285 LET k$="0"+STR$ kk
2290 LET k$=b$+k$(LEN k$-1 TO ): GO SUB 4000
2300 LET match=mod97=1
2310 REM Continue if mod 97
2320 IF NOT match THEN LET e$="result from modulo 97"
3000 IF match THEN PRINT " ": GO TO 3100
3010 PRINT "in";: LET e$=" ***error!*** invalid "+e$
3100 PRINT "valid IBAN: ";i$;e$: LET e$=""
3110 RETURN
4000 REM Modulo 97
4010 LET mod97=0
4020 FOR i=1 TO LEN k$
4030 LET d$=STR$ (mod97)+k$(i)
4040 LET mod97=FN m(VAL (d$),97)
4050 NEXT i
4060 RETURN
5000 DEF FN m(a,b)=a-INT (a/b)*b: REM modulo</syntaxhighlight>
9,485

edits