Кто-нибудь знает код проверки Vehicle Identification Number
( вики ), написанный на PHP? Мне просто нужно проверить правильность введенного номера вин?
Вот что я написал очень быстро, используя пример в статье wikipedia.
Не гарантируется безупречный или простой или суперэффективный, но должен обеспечить вам прочную отправную точку:
Примечание . Я включил исправления, приведенные ниже, и сделал процедуру несколько более кратким.
function validate_vin($vin) { $vin = strtolower($vin); if (!preg_match('/^[^\Wioq]{17}$/', $vin)) { return false; } $weights = array(8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2); $transliterations = array( "a" => 1, "b" => 2, "c" => 3, "d" => 4, "e" => 5, "f" => 6, "g" => 7, "h" => 8, "j" => 1, "k" => 2, "l" => 3, "m" => 4, "n" => 5, "p" => 7, "r" => 9, "s" => 2, "t" => 3, "u" => 4, "v" => 5, "w" => 6, "x" => 7, "y" => 8, "z" => 9 ); $sum = 0; for($i = 0 ; $i < strlen($vin) ; $i++ ) { // loop through characters of VIN // add transliterations * weight of their positions to get the sum if(!is_numeric($vin{$i})) { $sum += $transliterations[$vin{$i}] * $weights[$i]; } else { $sum += $vin{$i} * $weights[$i]; } } // find checkdigit by taking the mod of the sum $checkdigit = $sum % 11; if($checkdigit == 10) { // checkdigit of 10 is represented by "X" $checkdigit = "x"; } return ($checkdigit == $vin{8}); }
Примечание : при проверке VIN существует небольшая процентная ошибка из-за характера контрольной суммы:
… совпадение не доказывает, что VIN является правильным, потому что все еще существует вероятность 1 из 11 любых двух разных VIN, имеющих соответствующую контрольную цифру.
Также обратите внимание : 11111111111111111
будет проверять процедуру выше. Независимо от того, хотите ли вы проверить это, зависит от вас:
Прямым (семнадцать последовательных «1») хватит контрольной цифры. Это связано с тем, что значение одного, умноженное на 89 (сумма весов), все равно 89. И 89% 11 равно 1 контрольной цифре. Это простой способ проверить алгоритм проверки VIN.
ссылка: http://en.wikipedia.org/wiki/Vehicle_identification_number#Check_digit_calculation
Вот версия кода от jordan портирована на Javascript, надеюсь, что это кому-то полезно …
function validate_vin(vin) { function isnumeric(mixed_var) { return (typeof(mixed_var) === 'number' || typeof(mixed_var) === 'string') && mixed_var !== '' && !isNaN(mixed_var); } var pattern = /^[^\Wioq]{17}$/; var weights = Array(8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2); var transliterations = { "a" : 1, "b" : 2, "c" : 3, "d" : 4, "e" : 5, "f" : 6, "g" : 7, "h" : 8, "j" : 1, "k" : 2, "l" : 3, "m" : 4, "n" : 5, "p" : 7, "r" : 9, "s" : 2, "t" : 3, "u" : 4, "v" : 5, "w" : 6, "x" : 7, "y" : 8, "z" : 9 }; vin = vin.toLowerCase(); if(!vin.match(pattern)) { return false; } var sum = 0; for(var i=0; i<vin.length; i++) { if(!isnumeric(vin.charAt(i))) { sum += transliterations[vin.charAt(i)] * weights[i]; } else { sum += parseInt(vin.charAt(i)) * weights[i]; } } var checkdigit = sum % 11; if(checkdigit == 10) { // check digit of 10 represented by X checkdigit = 'x'; } return (checkdigit == vin.charAt(8)); }
Это «VIN». «Номер VIN» = «Идентификационный номер транспортного средства», который не имеет смысла.
Здесь вы можете увидеть определение структуры VIN:
http://en.wikipedia.org/wiki/Vehicle_identification_number
И вы можете работать оттуда, или вы можете захватить этот скрипт здесь:
http://www.geekpedia.com/code29_Check-if-VIN-number-is-valid.html
Вот улучшенная версия функции, опубликованной jordan:
$vin = "1M8GDM9AXKP042788"; function validate_vin($vin) { $vin = strtolower($vin); if (!preg_match('/^[^\Wioq]{17}$/', $vin)) { return false; } $weights = array(8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2); $transliterations = array( "a" => 1, "b" => 2, "c" => 3, "d" => 4, "e" => 5, "f" => 6, "g" => 7, "h" => 8, "j" => 1, "k" => 2, "l" => 3, "m" => 4, "n" => 5, "p" => 7, "r" => 9, "s" => 2, "t" => 3, "u" => 4, "v" => 5, "w" => 6, "x" => 7, "y" => 8, "z" => 9 ); $sum = 0; for($i = 0 ; $i < strlen($vin) ; $i++ ) { // loop through characters of VIN // add transliterations * weight of their positions to get the sum if(!is_numeric($vin{$i})) { $sum += $transliterations[$vin{$i}] * $weights[$i]; } else { $sum += $vin{$i} * $weights[$i]; } } // find checkdigit by taking the mod of the sum $checkdigit = $sum % 11; if($checkdigit == 10) { // checkdigit of 10 is represented by "X" $checkdigit = "x"; } return ($checkdigit == $vin{8}); }
Недавно мне пришлось написать класс проверки VIN с PHP. Я разместил свой класс для всех, чтобы использовать его по адресу: http://dev.strategystar.net/2012/05/validate-vin-checksum-with-php/
class VIN { public static $transliteration = array( 'A'=>1, 'B'=>2, 'C'=>3, 'D'=>4, 'E'=>5, 'F'=>6, 'G'=>7, 'H'=>8, 'J'=>1, 'K'=>2, 'L'=>3, 'M'=>4, 'N'=>5, 'P'=>7, 'R'=>9, 'S'=>2, 'T'=>3, 'U'=>4, 'V'=>5, 'W'=>6, 'X'=>7, 'Y'=>8, 'Z'=>9, ); public static $weights = array(8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2); /*** * The checksum method is used to validate whether or not a VIN is valid * It will return an array with two keys: status and message * The "status" will either be boolean TRUE or FALSE * The "message" will be a string describing the status */ public static function checksum($vin) { $vin = strtoupper($vin); $length = strlen($vin); $sum = 0; if($length != 17) { return array('status'=>false, 'message'=>'VIN is not the right length'); } for($x=0; $x<$length; $x++) { $char = substr($vin, $x, 1); if(is_numeric($char)) { $sum += $char * self::$weights[$x]; } else { if(!isset(self::$transliteration[$char])) { return array('status'=>false, 'message'=>'VIN contains an invalid character.'); } $sum += self::$transliteration[$char] * self::$weights[$x]; } } $remainder = $sum % 11; $checkdigit = $remainder == 10 ? 'X' : $remainder; if(substr($vin, 8, 1) != $checkdigit) { return array('status'=>false, 'message'=>'The VIN is not valid.'); } return array('status'=>true, 'message'=>'The VIN is valid.'); } }
Спасибо всем за алгоритм и т. Д., Которые я вижу в Википедии. Это версия, которую я собрал, основываясь на комментариях выше. Обратите внимание: есть проблемы с версиями выше, так как это 00000000000354888 возвращает OK для вина. Я взял то, что было выше, и добавил вариант сначала проверить год, если <1980, предположим, что это не 17-тидичный реальный vin (должен), а также, если есть последовательности одного символа, считайте недействительным. Это достаточно хорошо для моих потребностей, поскольку я сравниваю их с значениями, заполненными 0, если не 17. Также я знаю значение года, поэтому, если я проверю, что могу ускорить код, пропустив проверку vin (да, я мог бы поставить это перед функцией) lol bye !.
<?php /* ======================================================================================= PURPOSE: VIN Validation (Check-digit validation is compulsory for all road vehicles sold in North America.) DETAILS: Validates 17 digit VINs by checking their formatting USAGE: returns boolean or returns an array with a detailed message COMMENTS: This could be made more robust by checking the country codes etc.. MORE INFO: https://en.wikipedia.org/wiki/Vehicle_identification_number ======================================================================================= */ class vinValidation { public static $transliteration = array( 'A'=>1, 'B'=>2, 'C'=>3, 'D'=>4, 'E'=>5, 'F'=>6, 'G'=>7, 'H'=>8, 'J'=>1, 'K'=>2, 'L'=>3, 'M'=>4, 'N'=>5, 'P'=>7, 'R'=>9, 'S'=>2, 'T'=>3, 'U'=>4, 'V'=>5, 'W'=>6, 'X'=>7, 'Y'=>8, 'Z'=>9, ); public static $weights = array(8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2); public function validateVIN($vin, $ret_array_status = false, $year = null) { //validates US/NA 1980>= VINs, if before 1980, no vin standards, this returns false if (!empty($year) && preg_match("/^[0-9]{4}/", $year)) { if ($year < 1980) return ($ret_array_status ? array('status' => false, 'message' => 'Unable to check VIN, pre-dates 1980.') : false); } $vin_length = 17; // US vin requirements >= 1980 $vin = strtoupper(trim($vin)); $sum = 0; //if (!preg_match('/^[^\Wioq]{17}$/', $vin)) //return ($ret_array_status ? array('status'=>false, 'message'=>'VIN is not valid, not the right length.') : false); if (!preg_match('/^[A-HJ-NPR-Z0-9]{17}$/', $vin)) return ($ret_array_status ? array('status'=>false, 'message'=>'VIN is not valid, VIN formatting is incorrect.') : false); if (preg_match('/(\w)\1{5,}/', $vin)) return ($ret_array_status ? array('status'=>false, 'message'=>'VIN contains invalid repeating character sequence.') : false); for($x=0; $x < $vin_length; $x++) { $char = substr($vin, $x, 1); if(is_numeric($char)) { $sum += $char * self::$weights[$x]; } else { if(!isset(self::$transliteration[$char])) return ($ret_array_status ? array('status'=>false, 'message'=>'VIN contains an invalid character.') : false); $sum += self::$transliteration[$char] * self::$weights[$x]; } } $remainder = $sum % 11; $checkdigit = $remainder == 10 ? 'X' : $remainder; //echo " sum:".$sum." remain:".$remainder." check dig:".$checkdigit."\n"; if(substr($vin, 8, 1) != $checkdigit) return ($ret_array_status ? array('status'=>false, 'message'=>'The VIN is not valid, failed checksum.') : false); // all is good return true or a value and status. return ($ret_array_status ? array('status'=>true, 'message'=>'The VIN is valid, passed checksum.') : true); } }
ТЕСТИРОВАНИЕ:
$vinClass = new vinValidation(); // not long enough not val var_dump($vinClass->validateVIN('1I345678123456789', false, 2000)); var_dump($vinClass->validateVIN('1I345678123456789')); echo "-----------------------------------------------------------\n"; // not valid var_dump($vinClass->validateVIN('00000000012870842', true)); var_dump($vinClass->validateVIN('00000000012870842', 1968)); //assumes faulty by year var_dump($vinClass->validateVIN('00000000012870842')); echo "-----------------------------------------------------------\n"; // not valid var_dump($vinClass->validateVIN('00000000000354888', true)); var_dump($vinClass->validateVIN('00000000000354888')); echo "-----------------------------------------------------------\n"; // Fails Checksum test var_dump($vinClass->validateVIN('368TU79MXH4763452',false,2000)); var_dump($vinClass->validateVIN('368TU79MXH4763452')); echo "-----------------------------------------------------------\n"; // yachtzee, (returns true or array) ! var_dump($vinClass->validateVIN('WP1AF2A56GLB91679',true)); var_dump($vinClass->validateVIN('WP1AF2A56GLB91679'));