为何这段实现隔位乘2求和的C代码返回异常值?
问题分析与修复
你的代码出现异常结果,核心问题出在浮点数运算的精度误差,还有循环逻辑的小偏差,具体拆解如下:
1. pow函数的精度陷阱
pow(10, i)是浮点数运算,无法保证结果是精确的整数。比如pow(10,2)可能返回99.99999999999999而非精确的100。当你用credit_card / pow(...)时,浮点数转换会导致计算结果偏差,最终取模%10得到错误的数字,这就是你看到初始值完全不合理的原因。
2. 循环逻辑的小偏差
你需要从倒数第二位开始处理,但原代码依赖浮点数索引位的方式本身不可靠,不如直接用整数操作逐位遍历更稳妥。
修复后的代码
#include <stdio.h> // 计算数字的位数,用整数循环实现,避免浮点数误差 int len(long li) { if (li == 0) { return 1; } int count = 0; while (li > 0) { count++; li /= 10; } return count; } int main(void) { long credit_card = 378282246310005; int sum = 0; long temp = credit_card; // 先跳过最后一位(个位),从倒数第二位开始 temp /= 10; // 每隔一位处理一次,直到temp为0 int step = 0; while (temp > 0) { if (step % 2 == 0) { int digit = temp % 10; int doubled = digit * 2; // 累加乘积的各位数字:如果是两位数,拆成十位+个位;否则直接加 sum += (doubled >= 10) ? (doubled / 10 + doubled % 10) : doubled; printf("处理的数字:%d,乘2后:%d,当前累加值:%d\n", digit, doubled, sum); } temp /= 10; step++; } printf("最终累加结果:%d\n", sum); return 0; }
关键修复点
- 替换
pow为整数除法/10和取模%10,彻底避免浮点数精度问题; - 用
temp变量遍历信用卡号的每一位,先跳过个位,直接从倒数第二位开始处理; - 简化乘积的各位数字累加逻辑,不用调用
len函数,直接判断是否为两位数拆分相加; - 重写
len函数,用整数循环计数替代log10的浮点数实现,避免潜在误差。
关于你提到的“溢出迹象”
你删除%10 *2后看到的异常,本质还是pow导致的计算偏差,并非真正的整数溢出——你的信用卡号378282246310005是15位,long类型在多数系统是64位,完全能容纳这个数值,不存在溢出问题。
内容的提问来源于stack exchange,提问作者Alan
相关产品推荐
相关产品推荐

