PHP CUSIP Check num

时间:2014-02-17 11:55:52

标签: php algorithm

我需要能够根据其校验位验证CUSIP号码。由于维基百科,我有这个过程的psudocode,但到目前为止我还无法用PHP复制它。

可以找到Psudocode here

我的PHP:

    <?php
/**
    * function to return the check digit value of a cusip
    * @param $cusip
    *       the cusip for processing.
    * @return Int
    *       cusip check digit.
    */
    function cusip_checksum($cusip){
        $sum = 0;
        $rebuiltcusip = '';
        for($i = 1; $i <= 8; $i++){
            $c = substr($cusip, ($i - 1), 1); //$i needs to be 0, so as we start at 1, take 1 off.
            $rebuiltcusip .= $c;
            switch(true){
                case $c == '0': // ctype_digit(0) returns false, so checking for 0 here.
                    $v = $c;
                    watchdog("case 0: ", $v);
                break;
                case ctype_digit($c): //check if numeric
                    $v = $c;
                    watchdog("case ctype_digit: ", $v);
                break;
                case $c == '*':
                    $v = 36;
                    watchdog("case *: ", $v);
                break;
                case $c == '@':
                    $v = 37;
                    watchdog("case @: ", $v);
                break;
                case $c == '#':
                    $v = 38;
                    watchdog("case #: ", $v);
                break;
                case !ctype_digit($c): //check letter last as this check would pass with * @ or # so allow them to be checked first
                    $v = (ord($c) - 64) + 9; //set ordinal number, -64 as this returns ASKII value, then add 9.
                    watchdog("case not ctype_digit: ", $v);
                break;
            }
            if(($i % 2) == 0){ //check if odd
                $v = $v * 2;
                watchdog("case odd: ", $v);
            }

            $sum = $sum + ($v / 10) + ($v % 10);
            watchdog("sum end loop: ", $sum);
        }

        $ncd = (10 - ($sum % 10)) % 10;
        $rebuiltcusip .= $ncd;
        watchdog("rebuilt cusip: ", "Cusip: ".$cusip." Rebuilt: ".$rebuiltcusip);
        return $ncd;
    }
?>
看门狗只是我记录这个过程。

传入CUSIP:98986T108,其校验位值为8,实际返回值98986T104(校验位值为4)。

这样:

<?php
    print cusip_checksum('98986T108');
?>

应该返回8,它返回4.

有人能发现原因吗?

1 个答案:

答案 0 :(得分:2)

将分区包裹在floor()函数中,你就在那里:

$sum = $sum + floor($v / 10) + ($v % 10);

现在CUSIP中的Q值将为26.这将为$ sum添加2和6而不是添加2.6和6.

这是修正的最终功能。我通过路透社提取的17614 CUSIP进行了此操作,其中有11个没有匹配。这是关于我通常从路透社数据中看到的错误程度,所以我对这个例程充满信心。

/**
* function to return the check digit value of a cusip
* @param $cusip
*       the cusip for processing.
* @return Int
*       cusip check digit.
*/
function cusip_checksum($cusip){
    $sum = 0;
    $rebuiltcusip = '';
    for($i = 1; $i <= 8; $i++){
        $c = substr($cusip, ($i - 1), 1); //$i needs to be 0, so as we start at 1, take 1 off.
        $rebuiltcusip .= $c;
        switch(true){
            case $c == '0': // ctype_digit(0) returns false, so checking for 0 here.
                $v = $c;
                watchdog("case 0: ", $v);
            break;
            case ctype_digit($c): //check if numeric
                $v = $c;
                watchdog("case ctype_digit: ", $v);
            break;
            case $c == '*':
                $v = 36;
                watchdog("case *: ", $v);
            break;
            case $c == '@':
                $v = 37;
                watchdog("case @: ", $v);
            break;
            case $c == '#':
                $v = 38;
                watchdog("case #: ", $v);
            break;
            case !ctype_digit($c): //check letter last as this check would pass with * @ or # so allow them to be checked first
                $v = (ord($c) - 64) + 9; //set ordinal number, -64 as this returns ASKII value, then add 9.
                watchdog("case not ctype_digit: ", $v);
            break;
        }
        if(($i % 2) == 0){ //check if odd
            $v = $v * 2;
            watchdog("case odd: ", $v);
        }

        $sum = $sum + floor($v / 10) + ($v % 10);
        watchdog("sum end loop: ", $sum);
    }

    $ncd = (10 - ($sum % 10)) % 10;
    $rebuiltcusip .= $ncd;
    watchdog("rebuilt cusip: ", "Cusip: ".$cusip." Rebuilt: ".$rebuiltcusip);
    return $ncd;
}