You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言数字各位平方拼接函数处理大数值异常,求修复方案

数字各位平方拼接函数异常问题分析与修复

问题背景

需要实现一个函数,将输入的unsigned类型数字的每一位平方后拼接成整数返回。例如输入9191,返回811181(9²=81、1²=1)。编写的C语言函数及测试用例如下:

原实现代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX 128

unsigned long long square_digits (unsigned n)
{
  char n_str[MAX];
  char c_str[MAX];
  char s_result[MAX];
  unsigned long long converted, result;
  int i, len;
  
  sprintf(n_str, "%u", n);
  
  len = strlen(n_str);
  s_result[0] = '\0';
  
  for (i = 0; i < len; ++i)
  {
    converted = n_str[i] - '0';
    converted = converted * converted;
    
    sprintf(c_str, "%llu", converted);
    strcat(s_result, c_str);
  }
  
  result = strtol(s_result, NULL, 10);
  
    return result;
}

测试用例

unsigned long long square_digits (unsigned n);

#define do_test(n, expected)                                                                       \
do {                                                                                               \
    unsigned long long actual = square_digits(n);                                                  \
    cr_assert_eq(actual, expected, "for n = %u, expected %llu, but got %llu", n, expected, actual);\
} while (false)

Test(test_suite, sample_tests)
{
    do_test(      3212u,                9414ull);
    do_test(      2112u,                4114ull);
    do_test(         0u,                   0ull);
    do_test(       999u,              818181ull);
    do_test(     10001u,               10001ull);
    do_test(3210987654u,    9410816449362516ull);
    do_test(3999999999u, 9818181818181818181ull); // :p
    do_test(   UINT_MAX,  164811681364948125ull);
}

前6个测试用例均通过,但输入3999999999时,实际返回9223372036854775807,与预期的9818181818181818181不符。

问题原因

9223372036854775807是有符号64位整数(long long)的最大值。原代码中使用strtol函数进行字符串转整数操作,该函数返回的是long类型(多数系统为64位有符号整数)。当目标数值超过long的最大值时,strtol会返回LONG_MAX并设置errno为ERANGE。而测试用例中的预期值9818181818181818181是无符号64位整数,其值大于有符号64位整数的最大值,因此strtol无法正确转换,导致结果异常。

修复方案

将字符串转整数的函数从strtol替换为strtoull,该函数专门用于将字符串转换为unsigned long long类型,能够正确处理超出有符号整数范围的无符号数值。

修复后的代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX 128

unsigned long long square_digits (unsigned n)
{
  char n_str[MAX];
  char c_str[MAX];
  char s_result[MAX];
  unsigned long long converted, result;
  int i, len;
  
  sprintf(n_str, "%u", n);
  
  len = strlen(n_str);
  s_result[0] = '\0';
  
  for (i = 0; i < len; ++i)
  {
    converted = n_str[i] - '0';
    converted = converted * converted;
    
    sprintf(c_str, "%llu", converted);
    strcat(s_result, c_str);
  }
  
  result = strtoull(s_result, NULL, 10); // 替换为strtoull
  
  return result;
}

其他实现方式

可以避免字符串转换,直接通过数学运算实现,减少类型转换风险并提升效率:

数学运算实现

#include <stdio.h>

unsigned long long square_digits(unsigned n) {
    unsigned long long result = 0;
    if (n == 0) {
        return 0;
    }
    
    // 提取所有数字(逆序存储)
    int digits[20]; // 足够存储unsigned类型的所有位数
    int digit_count = 0;
    while (n > 0) {
        digits[digit_count++] = n % 10;
        n /= 10;
    }
    
    // 从高位到低位构建结果
    for (int i = digit_count - 1; i >= 0; --i) {
        unsigned long long square = (unsigned long long)digits[i] * digits[i];
        // 根据平方值的位数调整结果的倍数
        if (square < 10) {
            result = result * 10 + square;
        } else {
            result = result * 100 + square;
        }
    }
    
    return result;
}

该方法通过提取数字、反转顺序后直接计算拼接结果,无需依赖字符串操作,避免了类型转换带来的异常问题。


内容的提问来源于stack exchange,提问作者coed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 13:55:21