I have to validate an Estonian business ID (not a citizen ID). The ID is 9 numbers, but I think there might be a system of assigning them. For example, here is the Finnish validation with the last number as the checksum
if (preg_match('/^\d{7}-\d{1}$/', $user_input)) {
list($num, $control) = preg_split('[-]', $user_input);
// Add leading zeros if number is < 7
$num = str_pad($num, 7, 0, STR_PAD_LEFT);
$controlSum = 0;
$controlSum += (int)substr($num, 0, 1)*7;
$controlSum += (int)substr($num, 1, 1)*9;
$controlSum += (int)substr($num, 2, 1)*10;
$controlSum += (int)substr($num, 3, 1)*5;
$controlSum += (int)substr($num, 4, 1)*8;
$controlSum += (int)substr($num, 5, 1)*4;
$controlSum += (int)substr($num, 6, 1)*2;
$controlSum = $controlSum%11;
if ($controlSum == 0) {
return ($controlSum == $control) ? true : false;
} elseif ($controlSum >= 2 && $controlSum <= 10 ) {
return ((11 - $controlSum) == $control) ? true : false;
}
}
Usually there is a checksum for all of these types of IDs, so it's not just a matter of running a regex on it, but I can't find anything relating to Estonian businesses.
Any links to known libraries, examples would be appreciated. I'm working in PHP, but these could be in any language.
Thanks.
You can include a SOAP-Call from the European Commission https://ec.europa.eu/taxation_customs/vies/vatRequest.html
It should work like this (not 100% tested):
$vatId = "{{the vat id }}";
$client = new SoapClient("http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl");
if ($client) {
$cc = substr($vatId, 0, 2);
$vn = substr($vatId, 2);
$params = array('countryCode' => $cc, 'vatNumber' => $vn);
$result = $client->checkVat($params);
if ($result->valid == true) {
echo "VAT-ID ok";
}
} else {
die("connection failed");
}
I found this library, which answers my question
https://github.com/arthurdejong/python-stdnum/blob/master/stdnum/ee/registrikood.py
from stdnum.exceptions import *
from stdnum.util import clean, isdigits
def calc_check_digit(number):
"""Calculate the check digit."""
check = sum(((i % 9) + 1) * int(n)
for i, n in enumerate(number[:-1])) % 11
if check == 10:
check = sum((((i + 2) % 9) + 1) * int(n)
for i, n in enumerate(number[:-1])) % 11
return str(check % 10)
def compact(number):
"""Convert the number to the minimal representation. This strips the
number of any valid separators and removes surrounding whitespace."""
return clean(number, ' ').strip()
def validate(number):
"""Check if the number provided is valid. This checks the length and
check digit."""
number = compact(number)
if not isdigits(number):
raise InvalidFormat()
if len(number) != 8:
raise InvalidLength()
if number[0] not in '1789':
raise InvalidComponent()
if number[-1] != calc_check_digit(number):
raise InvalidChecksum()
return number
def is_valid(number):
"""Check if the number provided is valid. This checks the length and
check digit."""
try:
return bool(validate(number))
except ValidationError:
return False
Related
I am trying to make it so that my code displays if entered array of numbers can be divided into 2 groups, and if yes then it displays"yes" or if no then"no. The yes or no part works fine, but if the code says yes then I want the code to also display the 2 columns with the numbers, I tried a lot but I just can't figure it out, please help.
function helper(&$arr, $n, $start, $lsum, $rsum) {
if ($start == $n)
return $lsum == $rsum;
if ($arr[$start] % 5 == 0)
$lsum += $arr[$start];
else if ($arr[$start] % 3 == 0)
$rsum += $arr[$start];
else
return helper($arr, $n, $start + 1, $lsum + $arr[$start], $rsum)
|| helper($arr, $n, $start + 1, $lsum, $rsum + $arr[$start]);
return helper($arr, $n, $start + 1, $lsum, $rsum);
}
function splitArray($arr, $n) {
return helper($arr, $n, 0, 0, 0);
}
$arr = array( 7,1, 7,3,4,6);
$n = count($arr);
if (splitArray($arr, $n))
print("Yes");
else
print("No");
Provided you want to split them into two parts
Replace your code at the bottom with...
$arr = array( 7,1, 7,3,4,6);
$n = count($arr);
list($group1, $group2) = array_chunk($arr, ceil(count($arr) / 2)); //Split the initial array into 2 if you want 3 just change 2 to 3 and so forth
if (splitArray($arr, $n)){
echo "Yes";
print_r($group1);
print_r($group2); //Each array assigned to new variable
} else {
echo "No";
}
I want to convert a number into a string representation with a format similar to Stack Overflow reputation display.
e.g.
999 == '999'
1000 == '1,000'
9999 == '9,999'
10000 == '10k'
10100 == '10.1k'
Another approach that produces exactly the desired output:
function getRepString (rep) {
rep = rep+''; // coerce to string
if (rep < 1000) {
return rep; // return the same number
}
if (rep < 10000) { // place a comma between
return rep.charAt(0) + ',' + rep.substring(1);
}
// divide and format
return (rep/1000).toFixed(rep % 1000 != 0)+'k';
}
Check the output results here.
UPDATE:
CMS got the check and provides a superior answer. Send any more votes his way.
// formats a number similar to the way stack exchange sites
// format reputation. e.g.
// for numbers< 10000 the output is '9,999'
// for numbers > 10000 the output is '10k' with one decimal place when needed
function getRepString(rep)
{
var repString;
if (rep < 1000)
{
repString = rep;
}
else if (rep < 10000)
{
// removed my rube goldberg contraption and lifted
// CMS version of this segment
repString = rep.charAt(0) + ',' + rep.substring(1);
}
else
{
repString = (Math.round((rep / 1000) * 10) / 10) + "k"
}
return repString.toString();
}
Output:
getRepString(999) == '999'
getRepString(1000) == '1,000'
getRepString(9999) == '9,999'
getRepString(10000) == '10k'
getRepString(10100) == '10.1k'
Here is a function in PHP which is part of iZend - http://www.izend.org/en/manual/library/countformat:
function count_format($n, $point='.', $sep=',') {
if ($n < 0) {
return 0;
}
if ($n < 10000) {
return number_format($n, 0, $point, $sep);
}
$d = $n < 1000000 ? 1000 : 1000000;
$f = round($n / $d, 1);
return number_format($f, $f - intval($f) ? 1 : 0, $point, $sep) . ($d == 1000 ? 'k' : 'M');
}
Here is CMS's version in PHP (in case someone needed it, like I did):
function getRepString($rep) {
$rep = intval($rep);
if ($rep < 1000) {
return (string)$rep;
}
if ($rep < 10000) {
return number_format($rep);
}
return number_format(($rep / 1000), ($rep % 1000 != 0)) . 'k';
}
// TEST
var_dump(getRepString(999));
var_dump(getRepString(1000));
var_dump(getRepString(9999));
var_dump(getRepString(10000));
var_dump(getRepString(10100));
Output:
string(3) "999"
string(5) "1,000"
string(5) "9,999"
string(3) "10k"
string(5) "10.1k"
Handlebars.registerHelper("classNameHere",function(rep) {
var repString;
if (rep < 1000)
{
repString = rep;
}
else if (rep < 10000)
{
rep = String(rep);
r = rep.charAt(0);
s = rep.substring(1);
repString = r + ',' + s;
}
else
{
repDecimal = Math.round(rep / 100) / 10;
repString = repDecimal + "k";
}
return repString.toString();
});
divide by 1000 then if result is greater than 1 round the number and concantenate a "k" on the end.
If the result is less than 1 just output the actual result!
// Shortens a number and attaches K, M, B, etc. accordingly
function number_shorten($number, $precision = 3, $divisors = null) {
// Setup default $divisors if not provided
if (!isset($divisors)) {
$divisors = array(
pow(1000, 0) => '', // 1000^0 == 1
pow(1000, 1) => 'K', // Thousand
pow(1000, 2) => 'M', // Million
pow(1000, 3) => 'B', // Billion
pow(1000, 4) => 'T', // Trillion
pow(1000, 5) => 'Qa', // Quadrillion
pow(1000, 6) => 'Qi', // Quintillion
);
}
// Loop through each $divisor and find the
// lowest amount that matches
foreach ($divisors as $divisor => $shorthand) {
if (abs($number) < ($divisor * 1000)) {
// We found a match!
break;
}
}
// We found our match, or there were no matches.
// Either way, use the last defined value for $divisor.
return number_format($number / $divisor, $precision) . $shorthand;
}
This worked for me. I hope, this will help you. Thanks for asking this question.
I created an npm (and bower) module to do this:
npm install --save approximate-number
Usage:
var approx = require('approximate-number');
approx(123456); // "123k"
I have a large number that I want to split in half. For this example, let's use: 5639445604728832
When it is split in half it comes out like this:
56394456
04728832
Obviously, the second number isn't a number anymore.
I have the following code, but I am trying to make it so it will add the 0's to the end of the first number until the second number is officially a real number. Could anyone help me solve this?
function my_number_split($number)
{
$half = (int) ( (strlen($number) / 2) ); // cast to int incase str length is odd
$left = substr($number, 0, $half);
$right = substr($number, $half);
echo $left."<br />".$right;
}
Rewriting your function like this would do the trick.
function my_number_split($number)
{
$half = ceil( (strlen($number) / 2) );
while (0 == substr($number, $half, 1) && $half <= strlen($number) ) $half++;
$left = substr($number, 0, $half);
$right = substr($number, $half);
echo $left."<br />".$right;
}
Simple loop should do it.
Something like this -
function my_number_split($number)
{
/* Logic to traverse ahead till a 0 is not found. */
$str_len = strlen($number);
$half_index = $str_len/2;
while($half_index < $str_len){
if($number[$half_index] != "0"){
break;
}
$half_index++;
}
//Slicing string.
$left = substr($number, 0, $half_index);
$right = substr($number, $half_index);
echo $left."<br />".$right;
}
my_number_split("5639445604728832");
/*
OUTPUT -
563944560
4728832
*/
It's probably an inefficient way, but for the challenge:
if (preg_match('~\A(?<n1>.?(?:.(?=.*(.(?(2)\2)\z)))+0*)(?<n2>.+)~', $number, $m))
echo $m['n1'] . "\n" . $m['n2'];
How can I calculate the n-th root of an integer using PHP/GMP?
Although I found a function called gmp_root(a, nth) in the PHP source, it seems that this function has not been published in any release yet*: http://3v4l.org/8FjU7
*) 5.6.0alpha2 being the most recent one at the time of writing
Original source: Calculating Nth root with bcmath in PHP – thanks and credits to HamZa!
I've rewritten the code to use GMP instead of BCMath:
function gmp_nth_root($num, $n) {
if ($n < 1) return 0; // we want positive exponents
if ($num <= 0) return 0; // we want positive numbers
if ($num < 2) return 1; // n-th root of 1 or 2 give 1
// g is our guess number
$g = 2;
// while (g^n < num) g=g*2
while (gmp_cmp(gmp_pow($g, $n), $num) < 0) {
$g = gmp_mul($g, 2);
}
// if (g^n==num) num is a power of 2, we're lucky, end of job
if (gmp_cmp(gmp_pow($g, $n), $num) == 0) {
return $g;
}
// if we're here num wasn't a power of 2 :(
$og = $g; // og means original guess and here is our upper bound
$g = gmp_div($g, 2); // g is set to be our lower bound
$step = gmp_div(gmp_sub($og, $g), 2); // step is the half of upper bound - lower bound
$g = gmp_add($g, $step); // we start at lower bound + step , basically in the middle of our interval
// while step != 1
while (gmp_cmp($step, 1) > 0) {
$guess = gmp_pow($g, $n);
$step = gmp_div($step, 2);
$comp = gmp_cmp($guess, $num); // compare our guess with real number
if ($comp < 0) { // if guess is lower we add the new step
$g = gmp_add($g, $step);
} else if ($comp == 1) { // if guess is higher we sub the new step
$g = gmp_sub($g, $step);
} else { // if guess is exactly the num we're done, we return the value
return $g;
}
}
// whatever happened, g is the closest guess we can make so return it
return $g;
}
There are lots of implementations for validating Luhn checksums but very few for generating them. I've come across this one however in my tests it has revealed to be buggy and I don't understand the logic behind the delta variable.
I've made this function that supposedly should generated Luhn checksums but for some reason that I haven't yet understood the generated checksums are invalid half of the time.
function Luhn($number, $iterations = 1)
{
while ($iterations-- >= 1)
{
$stack = 0;
$parity = strlen($number) % 2;
$number = str_split($number, 1);
foreach ($number as $key => $value)
{
if ($key % 2 == $parity)
{
$value *= 2;
if ($value > 9)
{
$value -= 9;
}
}
$stack += $value;
}
$stack = 10 - $stack % 10;
if ($stack == 10)
{
$stack = 0;
}
$number[] = $stack;
}
return implode('', $number);
}
Some examples:
Luhn(3); // 37, invalid
Luhn(37); // 372, valid
Luhn(372); // 3728, invalid
Luhn(3728); // 37283, valid
Luhn(37283); // 372837, invalid
Luhn(372837); // 3728375, valid
I'm validating the generated checksums against this page, what am I doing wrong here?
For future reference, here is the working function.
function Luhn($number, $iterations = 1)
{
while ($iterations-- >= 1)
{
$stack = 0;
$number = str_split(strrev($number), 1);
foreach ($number as $key => $value)
{
if ($key % 2 == 0)
{
$value = array_sum(str_split($value * 2, 1));
}
$stack += $value;
}
$stack %= 10;
if ($stack != 0)
{
$stack -= 10;
}
$number = implode('', array_reverse($number)) . abs($stack);
}
return $number;
}
I dropped the $parity variable since we don't need it for this purpose, and to verify:
function Luhn_Verify($number, $iterations = 1)
{
$result = substr($number, 0, - $iterations);
if (Luhn($result, $iterations) == $number)
{
return $result;
}
return false;
}
Edit: Sorry, I realize now that you had almost my entire answer already, you had just incorrectly determined which factor to use for which digit.
My entire answer now can be summed up with this single sentence:
You have the factor reversed, you're multiplying the wrong digits by 2 depending on the length of the number.
Take a look at the Wikipedia article on the Luhn algorithm.
The reason your checksum is invalid half the time is that with your checks, half the time your number has an odd number of digits, and then you double the wrong digit.
For 37283, when counting from the right, you get this sequence of numbers:
3 * 1 = 3 3
8 * 2 = 16 --> 1 + 6 = 7
2 * 1 = 2 2
7 * 2 = 14 --> 1 + 4 = 5
+ 3 * 1 = 3 3
= 20
The algorithm requires you to sum the individual digits from the original number, and the individual digits of the product of those "every two digits from the right".
So from the right, you sum 3 + (1 + 6) + 2 + (1 + 4) + 3, which gives you 20.
If the number you end up with ends with a zero, which 20 does, the number is valid.
Now, your question hints at you wanting to know how to generate the checksum, well, that's easy, do the following:
Tack on an extra zero, so your number goes from xyxyxyxy to xyxyxyxy0
Calculate the luhn checksum sum for the new number
Take the sum, modulus 10, so you get a single digit from 0 to 10
If the digit is 0, then congratulations, your checksum digit was a zero
Otherwise, calculate 10-digit to get what you need for the last digit, instead of that zero
Example: Number is 12345
Tack on a zero: 123450
Calculate the luhn checksum for 123450, which results in
0 5 4 3 2 1
1 2 1 2 1 2 <-- factor
0 10 4 6 2 2 <-- product
0 1 0 4 6 2 2 <-- sum these to: 0+1+0+4+6+2+2=15
Take the sum (15), modulus 10, which gives you 5
Digit (5), is not zero
Calculate 10-5, which gives you 5, the last digit should be 5.
So the result is 123455.
your php is buggy, it leads into an infinite loop.
This is the working version that I'm using, modified from your code
function Luhn($number) {
$stack = 0;
$number = str_split(strrev($number));
foreach ($number as $key => $value)
{
if ($key % 2 == 0)
{
$value = array_sum(str_split($value * 2));
}
$stack += $value;
}
$stack %= 10;
if ($stack != 0)
{
$stack -= 10; $stack = abs($stack);
}
$number = implode('', array_reverse($number));
$number = $number . strval($stack);
return $number;
}
Create a php and run in your localhost Luhn(xxxxxxxx) to confirm.
BAD
I literally cannot believe how many crummy implementations there are out there.
IDAutomation has a .NET assembly with a MOD10() function to create but it just doesn't seem to work. In Reflector the code is way too long for what it's supposed to be doing anyway.
BAD
This mess of a page which is actually currently linked to from Wikipedia(!) for Javascript has several verification implementations that don't even return the same value when I call each one.
GOOD
The page linked to from Wikipedia's Luhn page has a Javascript encoder which seems to work :
// Javascript
String.prototype.luhnGet = function()
{
var luhnArr = [[0,1,2,3,4,5,6,7,8,9],[0,2,4,6,8,1,3,5,7,9]], sum = 0;
this.replace(/\D+/g,"").replace(/[\d]/g, function(c, p, o){
sum += luhnArr[ (o.length-p)&1 ][ parseInt(c,10) ]
});
return this + ((10 - sum%10)%10);
};
alert("54511187504546384725".luhnGet());
GOOD
This very useful EE4253 page verifies the check-digit and also shows the full calculation and explanation.
GOOD
I needed C# code and ended up using this code project code:
// C#
public static int GetMod10Digit(string data)
{
int sum = 0;
bool odd = true;
for (int i = data.Length - 1; i >= 0; i--)
{
if (odd == true)
{
int tSum = Convert.ToInt32(data[i].ToString()) * 2;
if (tSum >= 10)
{
string tData = tSum.ToString();
tSum = Convert.ToInt32(tData[0].ToString()) + Convert.ToInt32(tData[1].ToString());
}
sum += tSum;
}
else
sum += Convert.ToInt32(data[i].ToString());
odd = !odd;
}
int result = (((sum / 10) + 1) * 10) - sum;
return result % 10;
}
GOOD
This validation code in C# seems to work, if a little unwieldy. I just used it to check the above was correct.
There's now a github repo based on the original question/answer. See
https://github.com/xi-project/xi-algorithm
It's also available at packagist
This is a function that could help you, it's short and it works just fine.
function isLuhnValid($number)
{
if (empty($number))
return false;
$_j = 0;
$_base = str_split($number);
$_sum = array_pop($_base);
while (($_actual = array_pop($_base)) !== null) {
if ($_j % 2 == 0) {
$_actual *= 2;
if ($_actual > 9)
$_actual -= 9;
}
$_j++;
$_sum += $_actual;
}
return $_sum % 10 === 0;
}
Since the other answers that displayed or linked to C# weren't working, I've added a tested and more explanatory C# version:
/// <summary>
/// Calculates Luhn Check Digit based on
/// https://en.wikipedia.org/wiki/Luhn_algorithm
/// </summary>
/// <param name="digits">The digits EXCLUDING the check digit on the end.
/// The check digit should be compared against the result of this method.
/// </param>
/// <returns>The correct checkDigit</returns>
public static int CalculateLuhnCheckDigit(int[] digits)
{
int sum = 0;
bool isMultiplyByTwo = false;
//Start the summing going right to left
for (int index = digits.Length-1; index >= 0; --index)
{
int digit = digits[index];
//Every other digit should be multipled by two.
if (isMultiplyByTwo)
digit *= 2;
//When the digit becomes 2 digits (due to digit*2),
//we add the two digits together.
if (digit > 9)
digit = digit.ToString()
.Sum(character => (int)char.GetNumericValue(character));
sum += digit;
isMultiplyByTwo = !isMultiplyByTwo;
}
int remainder = sum % 10;
//If theres no remainder, the checkDigit is 0.
int checkDigit = 0;
//Otherwise, the checkDigit is the number that gets to the next 10
if (remainder != 0)
checkDigit = 10 - (sum % 10);
return checkDigit;
}
An example of its use:
public static bool IsValid(string userValue)
{
//Get the check digit from the end of the value
int checkDigit = (int)char.GetNumericValue(userValue[userValue.Length - 1]);
//Remove the checkDigit for the luhn calculation
userValue = userValue.Substring(0, userValue.Length - 1);
int[] userValueDigits = userValue.Select(ch => (int)char.GetNumericValue(ch))
.ToArray();
int originalLuhnDigit = CalculateLuhnCheckDigit(userValueDigits);
//If the user entered check digit matches the calcuated one,
//the number is valid.
return checkDigit == originalLuhnDigit;
}
The parity check must start from the right.
Try this:
<?php
function Luhn($digits) {
$sum = 0;
foreach (str_split(strrev($digits)) as $i => $digit) {
$sum += ($i % 2 == 0) ? array_sum(str_split($digit * 2)) : $digit;
}
return $digits . (10 - ($sum % 10)) % 10;
}
Add Luhn checksum to $input
$digits = Luhn($input);
Verify a number with Luhn checksum in it:
if ($digits == Luhn(substr($digits, 0, -1))) {
// ...
}
Get the checksum number:
$luhn_digit = substr(Luhn($digits), -1);
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
int *LONT, n, TARF;
int SEGVT = 0;
int SEGVT2 = 0;
string TARJETA;
double VA;
cout << "cuantos digitos tiene la tarjeta: " << endl;
cin >> n;
LONT = new int[n];
do {
cout << "ingrese el # de la tarjeta: " << endl;
cin >> TARJETA;
VA = stod(TARJETA);
} while (VA < 0);
for (int POS = 0; POS < TARJETA.size(); POS++) {
LONT[POS] = TARJETA[POS] - '0';
}
for (int i = 0; i < n; i++) {
if (i % 2 == 0) {
LONT[i] = TARJETA[i] - '0';
LONT[i] = LONT[i] * 2;
if (LONT[i] >= 10) {
LONT[i] = LONT[i] - 9;
}
SEGVT2 = SEGVT2 + LONT[i];
}
else
{
LONT[i] = TARJETA[i] - '0';
SEGVT = SEGVT + LONT[i];
}
}
TARF = SEGVT + SEGVT2;
if (TARF % 10 == 0) {
cout << SEGVT2 << SEGVT;
cout << "El numero de tarjeta " << TARJETA << "; Es de una tarjeta valida (YA QUE SU MOD10 ES " << TARF << endl;
}
else
{
cout << SEGVT2 << SEGVT;
cout << "El numero de tarjeta" << TARJETA << "; No es de una tarjeta valida (YA QUE SU MOD10 ES " << TARF << endl;
}
delete[] LONT;
}