2013-04-22 64 views

Trả lời

7

http://en.wikipedia.org/wiki/International_Securities_Identification_Number

Thủ tục để tính ISIN số séc là tương tự như "Modulus 10 đúp Thêm đúp" kỹ thuật được sử dụng trong CUSIPs. Để tính số kiểm tra, trước tiên hãy chuyển đổi bất kỳ chữ cái nào thành số bằng cách thêm vị trí thứ tự của chúng trong bảng chữ cái thành 9, sao cho A = 10 và M = 22. Bắt đầu bằng chữ số đúng nhất, mọi chữ số khác được nhân với hai. (Đối với các số kiểm tra CUSIP, hai bước này được đảo ngược.) Chuỗi ký tự kết quả (số lớn hơn 9 trở thành hai chữ số riêng biệt) được thêm vào. Trừ số tiền này từ số nhỏ nhất kết thúc bằng số không lớn hơn hoặc bằng nó: số này cho biết số kiểm tra, còn được gọi là số mười của số tiền modulo 10. Tức là, tổng kết quả, bao gồm cả séc- chữ số, là bội số của 10.

Chúng cũng có một số good example.

+0

mô tả đó có một số sai lầm: "... mọi chữ số khác được nhân với hai". Như tôi có thể tìm thấy trong các tài liệu tham khảo khác, và kiểm tra các ví dụ: Không phải mọi số khác nhưng các chữ số thay thế được nhân với hai. –

+0

@ PabloFranciscoPérezHidalgo: hoàn toàn hợp lý để hiểu "mọi chữ số khác" có nghĩa là 'chữ số thay thế'. Nó không rõ ràng những gì bạn nghĩ rằng những sai lầm (s) trong mục Wikipedia là. –

2

Dựa trên các ví dụ được công bố trên Wikipedia, phương pháp này là:

  1. Thay thế mỗi chữ cái bằng thứ tự của nó (A = 1, B = 2 và vân vân) cộng 9 ->enter image description here
  2. Đối với mỗi chữ số ở vị trí chẵn bắt đầu từ vị trí ngoài cùng bên phải (enter image description here), thay thế bằng các chữ số của dấu hai chấm (hai chữ số trong hai mục nhập vectơ) ->enter image description here; đang
  3. Mã xác nhận:

enter image description here

Một thực thể trong JavaScript là:

function getVerificationCode(isin) 
{ 
if(isin.length != 12) return null; 
var v = []; 
for(var i = isin.length-2; i >= 0; i--) 
{ 
    var c = isin.charAt(i); 
    if(isNaN(c)) //Not a digit 
    { 
     var letterCode = isin.charCodeAt(i)-55; //Char ordinal + 9 
     v.push(letterCode % 10); 
     if(letterCode > 9) 
      v.push(Math.floor(letterCode/10)); 
    } 
    else 
     v.push(Number(c)); 
} 
var sum = 0; 
var l = v.length; 
for(var i = 0; i < l; i++) 
    if(i % 2 == 0) 
{ 
    var d = v[i]*2; 
    sum += Math.floor(d/10); 
    sum += d % 10; 
} 
else 
    sum += v[i]; 
return 10 - (sum % 10); 
} 

EDIT: Để đưa @queso cập nhật:

function getVerificationCode(isin) { 
    if (isin.length != 12) return false; 
    var v = []; 
    for (var i = isin.length - 2; i >= 0; i--) { 
     var c = isin.charAt(i); 
     if (isNaN(c)) { //not a digit 
      var letterCode = isin.charCodeAt(i) - 55; //Char ordinal + 9 
      v.push(letterCode % 10); 
      if (letterCode > 9) { 
       v.push(Math.floor(letterCode/10)); 
      } 
     } else { 
      v.push(Number(c)); 
     } 
    } 
    var sum = 0; 
    var l = v.length; 
    for (var i = 0; i < l; i++) { 
     if (i % 2 == 0) { 
      var d = v[i] * 2; 
      sum += Math.floor(d/10); 
      sum += d % 10; 
     } else { 
      sum += v[i]; 
     } 
    } 
    return (10 - (sum % 10)) % 10 
} 
+1

Đối với mã ở trên, ISIN XS0977502110 không tìm thấy ở đây: http://en.wikipedia.org/wiki/International_Securities_Identification_Number#External_links Tôi đã có thể cập nhật mã của bạn ở đây http://jsfiddle.net/markbenda/nh2w1Lbh/16/. Cảm ơn vì đã làm phần khó khăn. – Queso

+0

@Queo Tôi đã chỉnh sửa câu trả lời của mình để bao gồm các đề xuất mã của bạn. Cảm ơn những cải tiến! –

7

Building trên các ví dụ của những người khác, đây là một triển khai C# sẽ xác nhận cả hai ISIN và CUSIP (và có thể một số biến thể Luhn khác).

Cách sử dụng:

foreach (var isin in ValidIsins) 
{ 
    var calculatedChecksum = SecuritiesValidation.CalculateChecksum(isin.Substring(0, 11)); 
    var actualChecksum = (isin.Last() - '0'); 
    Assert.AreEqual(calculatedChecksum, actualChecksum); 
} 
foreach (var cusip in ValidCusips) 
{ 
    var calculatedChecksum = SecuritiesValidation.CalculateChecksum(cusip.Substring(0, 8), true, true); 
    var actualChecksum = (cusip.Last() - '0'); 
    Assert.AreEqual(calculatedChecksum, actualChecksum); 
} 

Thực hiện:

public static class SecuritiesValidation 
{ 
    public static int CalculateChecksum(IEnumerable<char> codeWithoutChecksum, bool reverseLuhn = false, bool allowSymbols = false) 
    { 
     return reverseLuhn 
      ? codeWithoutChecksum 
       .Select((c, i) => c.OrdinalPosition(allowSymbols).ConditionalMultiplyByTwo(i.IsOdd()).SumDigits()) 
       .Sum() 
       .TensComplement() 
      : codeWithoutChecksum 
       .ToArray() 
       .ToDigits(allowSymbols) 
       .Select((d, i) => d.ConditionalMultiplyByTwo(i.IsEven()).SumDigits()) 
       .Sum() 
       .TensComplement(); 
    } 

    public static bool IsChecksumCorrect(string code, bool reverseLuhn = false, bool allowSymbols = false) 
    { 
     try 
     { 
      var checksum = code.Last().ToInt(); 
      return checksum == CalculateChecksum(code.Take(code.Length - 1), reverseLuhn, allowSymbols); 
     } 
     catch 
     { 
      return false; 
     } 
    } 

    /* Be careful here. This method is probably inapropriate for anything other than its designed purpose of Luhn-algorithm based validation. 
    * Specifically: 
    * - numbers are assigned a value equal to the number ('0' == 0, '1' == 1). 
    * - letters are assigned a value indicating the number 9 plus the letters ordinal position in the English alphabet ('A' == 10, 'B' == 11). 
    * - if symbols are allowed (eg: for CUSIP validation), they are assigned values beginning from 36 ('*' == 36, '@' == 37). 
    */ 
    private static int OrdinalPosition(this char c, bool allowSymbols = false) 
    { 
     if (char.IsLower(c)) 
      return char.ToUpper(c) - 'A' + 10; 

     if (char.IsUpper(c)) 
      return c - 'A' + 10; 

     if (char.IsDigit(c)) 
      return c.ToInt(); 

     if (allowSymbols) 
      switch (c) 
      { 
       case '*': 
        return 36; 
       case '@': 
        return 37; 
       case '#': 
        return 38; 
      } 
     throw new ArgumentOutOfRangeException("Specified character is not a letter, digit or allowed symbol."); 
    } 

    private static bool IsEven(this int x) 
    { 
     return (x % 2 == 0); 
    } 

    private static bool IsOdd(this int x) 
    { 
     return !IsEven(x); 
    } 

    private static int ToInt(this char digit) 
    { 
     if (char.IsDigit(digit)) 
      return digit - '0'; 
     throw new ArgumentOutOfRangeException("Specified character is not a digit."); 
    } 

    private static IEnumerable<int> ToDigits(this char[] s, bool allowSymbols = false) 
    { 
     var digits = new List<int>(); 
     for (var i = s.Length - 1; i >= 0; i--) 
     { 
      var ordinalPosition = s[i].OrdinalPosition(allowSymbols); 
      digits.Add(ordinalPosition % 10); 
      if (ordinalPosition > 9) 
       digits.Add(ordinalPosition/10); 
     } 
     return digits; 
    } 

    private static int SumDigits(this int value) 
    { 
     //return value > 9 ? ((value/10) + (value % 10)) : value; 
     return ((value/10) + (value % 10)); 
    } 

    private static int ConditionalMultiplyByTwo(this int value, bool condition) 
    { 
     return condition ? value * 2 : value; 
    } 

    private static int TensComplement(this int value) 
    { 
     return (10 - (value % 10)) % 10; 
    } 
} 

Nó sẽ có khả năng làm cho cảm giác sử dụng xác nhận checksum kết hợp với một mô hình phù hợp biểu thức chính quy. Đây là những regex tôi sử dụng:

ISIN: ^(XS|AD|AE|AF|AG|AI|AL|AM|AO|AQ|AR|AS|AT|AU|AW|AX|AZ|BA|BB|BD|BE|BF|BG|BH|BI|BJ|BL|BM|BN|BO|BQ|BR|BS|BT|BV|BW|BY|BZ|CA|CC|CD|CF|CG|CH|CI|CK|CL|CM|CN|CO|CR|CU|CV|CW|CX|CY|CZ|DE|DJ|DK|DM|DO|DZ|EC|EE|EG|EH|ER|ES|ET|FI|FJ|FK|FM|FO|FR|GA|GB|GD|GE|GF|GG|GH|GI|GL|GM|GN|GP|GQ|GR|GS|GT|GU|GW|GY|HK|HM|HN|HR|HT|HU|ID|IE|IL|IM|IN|IO|IQ|IR|IS|IT|JE|JM|JO|JP|KE|KG|KH|KI|KM|KN|KP|KR|KW|KY|KZ|LA|LB|LC|LI|LK|LR|LS|LT|LU|LV|LY|MA|MC|MD|ME|MF|MG|MH|MK|ML|MM|MN|MO|MP|MQ|MR|MS|MT|MU|MV|MW|MX|MY|MZ|NA|NC|NE|NF|NG|NI|NL|NO|NP|NR|NU|NZ|OM|PA|PE|PF|PG|PH|PK|PL|PM|PN|PR|PS|PT|PW|PY|QA|RE|RO|RS|RU|RW|SA|SB|SC|SD|SE|SG|SH|SI|SJ|SK|SL|SM|SN|SO|SR|SS|ST|SV|SX|SY|SZ|TC|TD|TF|TG|TH|TJ|TK|TL|TM|TN|TO|TR|TT|TV|TW|TZ|UA|UG|UM|US|UY|UZ|VA|VC|VE|VG|VI|VN|VU|WF|WS|YE|YT|ZA|ZM|ZW)([0-9A-Z]{9})([0-9]{1})$

CUSIP: ^[A-Z0-9]{8}[0-9]$

0

Tôi muốn chia sẻ thực hiện của tôi trong R. Nó không yêu cầu bất kỳ gói cụ thể.

mgsub là một chức năng hỗ trợ cho phép thay thế tất cả các ký tự trong mã ISIN trong một lệnh duy nhất. Nó được sao chép từ Replace multiple letters with accents with gsub

các iso3166alpha2$Code chứa danh sách các quốc gia mà Grenade đã liệt kê

Thuật toán được thực hiện trong các isIsin(x) chức năng, trong đó trả TRUE trong trường hợp của mã ISIN hợp lệ

mgsub <- function(pattern, replacement, x, ...) { 
    if (length(pattern)!=length(replacement)) { 
    stop("pattern and replacement do not have the same length.") 
    } 
    result <- x 
    for (i in 1:length(pattern)) { 
    result <- gsub(pattern[i], replacement[i], result, ...) 
    } 
    result 
} 

isIsin <- function (identifier) { 

    correctPrefix <- substr(identifier, 1, 2) %in% c(iso3166alpha2$Code, "XS") 

    correctLength <- nchar(identifier) == 12 

    correctCharset <- !grepl('[[:punct:]]', identifier) 

    if(!correctPrefix | !correctLength | !correctCharset) { 
    return(FALSE) 
    } 

    # replace all character with its equivalent number 
    identifierOnlyNumbers <- mgsub(LETTERS, seq(10, 35), substr(identifier, 1, 11)) 

    # split the identifier in single digits and reverse its order 
    characterVector <- rev(unlist(strsplit(identifierOnlyNumbers, ""))) 

    # Double every second digit of the group of digits with the rightmost character 
    characterVector[seq(1, nchar(identifierOnlyNumbers), 2)] <- 
    as.character(as.numeric(characterVector[seq(1, nchar(identifierOnlyNumbers), 2)]) * 2) 

    # Subtract 9 if > 9 (can apply to all since no digit can be greater than 9 before doubling) 
    # Add up the digits 
    summation <- sum(ifelse(as.numeric(characterVector) > 9, as.numeric(characterVector) - 9, as.numeric(characterVector))) 

    # Take the 10s modulus of the sum, subtract it from 10 and take the 10s modulus of the result 
    # this final step is important in the instance where the modulus of the sum is 0, as the resulting check digit would be 10 
    correctCheckDigit <- (10 - (summation %% 10)) %% 10 == as.numeric(substr(identifier, 12, 12)) 

    correctCheckDigit 

} 
Các vấn đề liên quan