The JavaScript and Python below follow the ABR's and ASIC's rules above. We ran both against every 11-digit ABN and 9-digit ACN on this page.
JavaScript
const ABN_WEIGHTS = [10, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19];
const ACN_WEIGHTS = [8, 7, 6, 5, 4, 3, 2, 1];
function isValidAbn(abn) {
const d = String(abn).replace(/\s/g, "");
if (!/^[1-9]\d{10}$/.test(d)) return false;
const digits = [...d].map(Number);
digits[0] -= 1;
const total = digits.reduce((sum, n, i) => sum + n * ABN_WEIGHTS[i], 0);
return total % 89 === 0;
}
function isValidAcn(acn) {
const d = String(acn).replace(/\s/g, "");
if (!/^\d{9}$/.test(d)) return false;
const total = [...d.slice(0, 8)].reduce((sum, n, i) => sum + Number(n) * ACN_WEIGHTS[i], 0);
return (10 - (total % 10)) % 10 === Number(d[8]);
}
// The full ABN, 2 check digits in front, for any 9-digit identifier such as an ACN.
function abnFromNineDigits(nine) {
const d = String(nine).replace(/\s/g, "");
const rest = [...d].reduce((sum, n, i) => sum + Number(n) * ABN_WEIGHTS[i + 2], 0);
return String(10 + ((89 - (rest % 89)) % 89)) + d;
}
Python
ABN_WEIGHTS = [10, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
ACN_WEIGHTS = [8, 7, 6, 5, 4, 3, 2, 1]
def is_valid_abn(abn: str) -> bool:
d = abn.replace(" ", "")
if len(d) != 11 or not d.isdigit() or d[0] == "0":
return False
digits = [int(c) for c in d]
digits[0] -= 1
return sum(n * w for n, w in zip(digits, ABN_WEIGHTS)) % 89 == 0
def is_valid_acn(acn: str) -> bool:
d = acn.replace(" ", "")
if len(d) != 9 or not d.isdigit():
return False
total = sum(int(n) * w for n, w in zip(d[:8], ACN_WEIGHTS))
return (10 - total % 10) % 10 == int(d[8])
def abn_from_nine_digits(nine: str) -> str:
"""The full ABN, 2 check digits in front, for any 9-digit identifier such as an ACN."""
d = nine.replace(" ", "")
rest = sum(int(n) * w for n, w in zip(d, ABN_WEIGHTS[2:]))
return str(10 + (89 - rest % 89) % 89) + d
A format check runs offline. To know whether a number is on the register, it has to be looked up: in the box above, or on ABN Lookup.