我有一个用于计算LUHN校验和的类。它将整数作为输入,返回true或false以指示有效性或其他方式,如果给出不适当的数据类型作为输入,则会抛出异常。

代码如下(完整源位于 github ):

class Luhn extends abstr\Prop implements iface\Prop
{
    /**
     * Test that the given data passes a Luhn check. 
     * 
     * @return bool True if the data passes the Luhn check
     * @throws \InvalidArgumentException 
     * @see http://en.wikipedia.org/wiki/Luhn_algorithm
     */
    public function isValid ()
    {
        $data   = $this -> getData ();
        $valid  = false;

        switch (gettype ($data))
        {
            case 'NULL'     :
                $valid  = true;
            break;
            case 'integer'  :
                // Get the sequence of digits that make up the number under test
                $digits = array_reverse (array_map ('intval', str_split ((string) $data)));
                // Walk the array, doubling the value of every second digit
                for ($i = 0, $count = count ($digits); $i < $count; $i++)
                {
                    if ($i % 2)
                    {
                        // Double the digit
                        if (($digits [$i] *= 2) > 9)
                        {
                            // Handle the case where the doubled digit is over 9
                            $digits [$i]    -= 10;
                            $digits []      = 1;
                        }
                    }
                }
                // The Luhn is valid if the sum of the digits ends in a 0
                $valid  = ((array_sum ($digits) % 10) === 0);
            break;
            default         :
                // An attempt was made to apply the check to an invalid data type
                throw new \InvalidArgumentException (__CLASS__ . ': This property cannot be applied to data of type ' . gettype ($data));
            break;
        }

        return ($valid);
    }
}
.

我还建立了一个完整的单元测试< / a>锻炼课程。

我的主要开发环境是运行64位构建PHP 5.3的工作站和OSX Lion下的Apache。我还使用运行64位Apache和PHP 5.4的笔记本电脑,也可以在Apache下。以及此我有一个运行64位Apache和PHP 5.3的Ubuntu Linux虚拟机。按预期的所有这些单元测试对所有这些进行了良好的。

我以为我可以在午餐期间的一些业余时间(Windows 7,XAMPP,32位PHP 5.3)用于在这个类是一部分的项目上工作,但我跑进的第一件事是失败的测试。

问题是,在32位构建PHP上,如果超过32位整数的限制,则该数字将静默变为浮动。我所提出的解决方案是有一个特殊的浮法案例。如果输入类型是浮点数,并且其值超出可以在int(php_int_min .. php_int_max)中可以表示的范围,那么我将number_format()它将其返回到一系列数字中。如果它在整数的范围内,那么我会抛出异常。 但是,这导致了自己的问题。我知道,从浮点数的浮点数,数字的分辨率越少,数量的分辨率(给定数字和下一个可用数字之间的增量越小)。从0开始有多远,在不可能以可靠地代表整数部分之前不可能代表数字的整数部分,您必须得到多远? (例如,我不确定是否真的很清楚,例如,例如,在分辨率低于一个int和下一个的分辨率下降之前,限制是1000。我可以输入比1000更大的数字,但是浮点数意味着它最终是1001.9并舍入它收益1002,这意味着我丢失了我感兴趣的价值。

是否可以检测分辨率的损耗将成为浮点数的问题?

编辑以添加:我假设我可以修改扩展以接受字符串而不是数字类型,然后验证它只包含正则表达式的数字或其他类似的技术,而是作为luhn - 可以某种方式是一系列不对我有权的数字。 PHP有能够处理Bignums的扩展,但它们是他们的扩展,这意味着它可能是一个可能部署在广泛的配置中的框架代码,我宁愿不依赖于这样的存在扩展如果可能。此外,以上都不是解决问题,如果您将PHP为BIG INT默默地将其转换为浮动。我需要一种检测到这一切的方法。

有帮助吗?

解决方案

如果需要精度,则不应使用floats。 而是,特别是因为要使用整数(如果我理解正确),则可以尝试使用gmp*函数: gmp - gnu多重精度

如果您无法使用该扩展,您可能会从中获取一些额外的想法

其他提示

如果需要精度,则不应使用floats。 而是,特别是因为要使用整数(如果我理解正确),您可以尝试使用bc*函数: bcmath任意精度数学

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top