哈沙德数是指能被其各位数字之和整除的正整数;例如18的各位数字之和为9,18÷9=2无余数,故为哈沙德数,而19因19÷10余9,不是哈沙德数。

什么是哈沙德数?先看判断逻辑
哈沙德数(Harshad number)指能被其各位数字之和整除的正整数。比如 18:各位和是 1 + 8 == 9,而 18 % 9 == 0,所以它是哈沙德数;19 就不是,因为 19 % (1 + 9) == 19 % 10 == 9 != 0。
注意:只对正整数定义,0 和负数不参与判断;数字位数不限,但需避免溢出(如用 int 处理超大数会出错)。
用 C++ 写一个安全的 isHarshad 函数
核心是拆各位、求和、取模。关键点在于:不能改原值(要用副本)、要处理 0 边界、避免除零。
- 用
long long接入参更稳妥,防止像2147483647这类大数在求和时没问题,但后续计算仍可能因类型窄而出错 - 逐位取模用
n % 10,然后n /= 10,直到n == 0 - 必须检查
digitSum == 0—— 实际上只会在输入为0时发生,但函数应显式拒绝 - 最终判断用
num % digitSum == 0,这里num是原始输入(未被破坏),digitSum是正整数
bool isHarshad(long long num) {
if (num <= 0) return false;
long long n = num;
long long digitSum = 0;
while (n > 0) {
digitSum += n % 10;
n /= 10;
}
if (digitSum == 0) return false; // 理论不会触发,但防御性写法
return num % digitSum == 0;
}常见错误:字符串转换 vs 数学拆解
有人用 std::to_string 转成字符串再遍历每个字符,看似直观,但有隐含成本和风险:
立即学习“C++免费学习笔记(深入)”;
- 构造临时
std::string对象,堆分配开销(尤其高频调用时) - 字符转数字写成
c - '0'没问题,但若忘记isdigit(c)检查(比如输入含符号或空格),行为未定义 - 对极大数(如
1e18)转字符串长度达 19,而数学方法最多循环约 60 次(2^64不到 20 位),两者实际差距不大,但数学法更直接、无依赖
除非你 already 在处理字符串输入(比如读自文件每行一个数),否则没必要绕一圈。
测试时容易漏掉的边界情况
光测 12、18、21 不够。这几个值必须覆盖:
-
1→ 各位和=1,1 % 1 == 0→ true -
10→ 和=1,10 % 1 == 0→ true(所有以 0 结尾的 10 的倍数都满足,只要和不为 0) -
100→ 和=1 → true -
11→ 和=2,11 % 2 == 1→ false -
LLONG_MAX(或接近它的数)→ 确保没整数溢出,digitSum最大不过 9×20=180,所以模运算是安全的
真正容易栽跟头的是把 num 和 n 混用,或者忘了 num 是原始值——一旦在循环里直接改 num,后面 num % digitSum 就错了。


















