银行卡号码校验算法
银行卡号码校验算法
背景
最近在办卡的时候发现,两个相邻的人办卡,他们的卡号乍一看并不是连续的,但是把最后一位除掉之后却是连续的,很容易猜想最后一位应该是校验位。
银行卡号码的校验规则
银行卡号码的校验采用Luhn算法,假设有银行卡号如下:
我们使用不同的颜色对奇数和偶数部分进行区分。
红色部分表示从右往左数奇数位,蓝色部分表示从右往左数偶数位。
对于偶数位(蓝色部分),我们保留原数:
constexpr auto even = [](int x) {
return x;
};
对于奇数位(红色部分),我们假设表示的各位数之和,则有:
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);
};
最后我们将每个奇数位和偶数位对应的结果全部相加并对取余,如果余数为则校验位为,否则用减去余数,即:
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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~