银行卡号码校验算法

银行卡号码校验算法

背景

最近在办卡的时候发现,两个相邻的人办卡,他们的卡号乍一看并不是连续的,但是把最后一位除掉之后却是连续的,很容易猜想最后一位应该是校验位。

银行卡号码的校验规则

银行卡号码的校验采用Luhn算法,假设有银行卡号如下:

alt text

图1

我们使用不同的颜色对奇数和偶数部分进行区分。

红色部分表示从右往左数奇数位,蓝色部分表示从右往左数偶数位。

对于偶数位(蓝色部分),我们保留原数:

f(x)=x

constexpr auto even = [](int x) {
    return x;
};

对于奇数位(红色部分),我们假设g(x)表示x的各位数之和,则有:

f(x)=g(2x)

constexpr auto odd = [](int x) {
    x *= 2;
    return x / 10 + x % 10;
};

这样我们就获得了每一位数字变化后的结果

constexpr auto check_digit = [](auto&& idx_and_digit) {
    auto [idx, digit] = idx_and_digit;
    int x = digit - '0';
    // Since C++ started with 0, we swap even and odd.
    return idx & 1 ? even(x) : odd(x);
};

最后我们将每个奇数位和偶数位对应的结果全部相加并对10取余,如果余数为0则校验位为0,否则用10减去余数,即:

s=Resultmod10S(x)={0,if s=0,10s,otherwise

constexpr int Luhn(std::string_view numbers) 
{
    auto rg = numbers | std::views::reverse | std::views::enumerate | std::views::transform(check_digit);

    int digit_sum = std::ranges::fold_left(rg, 0, std::plus<>()) % 10;

    return digit_sum == 0 ? 0 : 10 - digit_sum;
}

代码

// https://en.wikipedia.org/wiki/Luhn_algorithm

#include <string_view>
#include <ranges>
#include <algorithm>
#include <cstdlib>
#include <functional>

constexpr auto odd = [](int x) {
    x *= 2;
    return x / 10 + x % 10;
};

constexpr auto even = [](int x) {
    return x;
};

constexpr auto check_digit = [](auto&& idx_and_digit) {
    auto [idx, digit] = idx_and_digit;
    int x = digit - '0';
    return idx & 1 ? even(x) : odd(x); // Since C++ started with 0, we swap even and odd.
};

constexpr int Luhn(std::string_view numbers) 
{
    auto rg = numbers | std::views::reverse | std::views::enumerate | std::views::transform(check_digit);

    int digit_sum = std::ranges::fold_left(rg, 0, std::plus<>()) % 10;

    return digit_sum == 0 ? 0 : 10 - digit_sum;
}

int main(int argc, char const *argv[])
{
    static_assert(Luhn("62122802001416649") == 7);
    return 0;
}

posted @   鸿钧三清  Views(368)  Comments(0Edit  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示