سؤال

هناك الكثير من التطبيقات للتحقق من صحة مجاميع Luhn الاختبارية ولكن عدد قليل جدًا من التطبيقات لإنشائها.لقد صادفت هذا ولكن في اختباراتي تبين أنها عربات التي تجرها الدواب وأنا لا أفهم المنطق وراء متغير دلتا.

لقد قمت بإنشاء هذه الوظيفة التي من المفترض أن تولد مجاميع اختبارية Luhn ولكن لسبب ما لم أفهم بعد أن المجاميع الاختبارية التي تم إنشاؤها غير صالحة في نصف الوقت.

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);
}

بعض الأمثلة:

Luhn(3); // 37, invalid
Luhn(37); // 372, valid
Luhn(372); // 3728, invalid
Luhn(3728); // 37283, valid
Luhn(37283); // 372837, invalid
Luhn(372837); // 3728375, valid

أنا أقوم بالتحقق من صحة المجاميع الاختبارية التي تم إنشاؤها ضد هذه الصفحة, ، ما الخطأ الذي أفعله هنا؟


للرجوع إليها في المستقبل، وهنا وظيفة العمل.

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;
}

لقد أسقطت المتغير $parity لأننا لسنا بحاجة إليه لهذا الغرض، وللتحقق:

function Luhn_Verify($number, $iterations = 1)
{
    $result = substr($number, 0, - $iterations);

    if (Luhn($result, $iterations) == $number)
    {
        return $result;
    }

    return false;
}
هل كانت مفيدة؟

المحلول

يحرر:عذرًا، أدركت الآن أنك حصلت على إجابتي بالكامل تقريبًا، ولكنك حددت بشكل غير صحيح العامل الذي يجب استخدامه لأي رقم.

يمكن تلخيص إجابتي بالكامل الآن بهذه الجملة الواحدة:

لقد تم عكس العامل، فأنت تقوم بضرب الأرقام الخاطئة في 2 اعتمادًا على طول الرقم.


نلقي نظرة على مقالة ويكيبيديا عن خوارزمية Luhn.

السبب وراء كون المجموع الاختباري الخاص بك غير صالح في نصف الوقت هو أنه في الشيكات الخاصة بك، في نصف الوقت الذي يحتوي فيه رقمك على عدد فردي من الأرقام، ثم تقوم بمضاعفة الرقم الخاطئ.

بالنسبة للرقم 37283، عند العد من اليمين، تحصل على هذا التسلسل من الأرقام:

  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

تتطلب الخوارزمية منك جمع الأرقام الفردية من الرقم الأصلي، والأرقام الفردية لمنتج تلك "كل رقمين من اليمين".

ومن اليمين، اجمع 3 + (1 + 6) + 2 + (1 + 4) + 3، وهو ما يعطيك 20.

إذا كان الرقم الذي انتهيت إليه ينتهي بصفر، وهو ما يعني 20، فإن الرقم صالح.

الآن، سؤالك يشير إلى أنك تريد معرفة كيفية إنشاء المجموع الاختباري، حسنًا، هذا سهل، قم بما يلي:

  1. أضف صفرًا إضافيًا، بحيث ينتقل رقمك من xyxyxyxy إلى xyxyxyxy0
  2. احسب المجموع الاختباري luhn للرقم الجديد
  3. خذ المجموع، المعامل 10، بحيث تحصل على رقم واحد من 0 إلى 10
  4. إذا كان الرقم 0، فتهانينا، فإن رقم المجموع الاختباري الخاص بك كان صفرًا
  5. بخلاف ذلك، قم بحساب 10 أرقام للحصول على ما تحتاجه للرقم الأخير، بدلاً من ذلك الصفر

مثال:الرقم هو 12345

  1. المس على الصفر:123450
  2. احسب المجموع الاختباري luhn لـ 123450، والذي ينتج عنه

    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
    
  3. خذ المجموع (15)، المعامل 10، والذي يعطيك 5

  4. الرقم (5) ليس صفراً
  5. احسب 10-5، وهو ما يعطيك 5، يجب أن يكون الرقم الأخير 5.

والنتيجة هي 123455.

نصائح أخرى

PHP الخاص بك به خلل، ويؤدي إلى حلقة لا نهائية.هذه هي نسخة العمل التي أستخدمها، المعدلة من التعليمات البرمجية الخاصة بك

وظيفة لوهن(رقم $) {

$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; 

}

قم بإنشاء PHP وتشغيله في مضيفك المحلي Luhn(xxxxxxxxx) للتأكيد.

سيء

أنا حرفيًا لا أستطيع أن أصدق عدد التطبيقات الرديئة الموجودة هناك.

IDAutomation لديه تجميع .NET مع وظيفة MOD10() لإنشاء ولكن لا يبدو أنه يعمل.في Reflector، تكون التعليمات البرمجية طويلة جدًا بالنسبة لما يفترض أن تفعله على أي حال.


سيء

هذه الفوضى من الصفحة والذي تم ربطه حاليًا بالفعل من Wikipedia(!) لـ Javascript يحتوي على العديد من تطبيقات التحقق التي لا تُرجع حتى نفس القيمة عندما أقوم بالاتصال بكل واحدة منها.


جيد

ال صفحة مرتبطة بصفحة Luhn في ويكيبيديا يحتوي على برنامج تشفير جافا سكريبت والذي يبدو أنه يعمل:

// 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());​

جيد

هذا مفيد جدا EE4253 تقوم الصفحة بالتحقق من رقم التحقق وتظهر أيضًا الحساب الكامل والشرح.


جيد

كنت بحاجة إلى رمز C# وانتهى بي الأمر باستخدام هذا رمز مشروع الكود:

// 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;
        }

جيد

هذا رمز التحقق في C# يبدو أنه يعمل، إذا كان غير عملي بعض الشيء.لقد استخدمته فقط للتحقق من صحة ما ورد أعلاه.

يوجد الآن مستودع جيثب بناءً على السؤال/الإجابة الأصلية.يرى

https://github.com/xi-project/xi-algorithm

إنه متوفر أيضًا لدى packagist

هذه وظيفة يمكن أن تساعدك، وهي قصيرة وتعمل بشكل جيد.

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;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top