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

C程序中18位十六进制转十进制结果错误的解决求助

解决18位十六进制转十进制的溢出与字符转换问题

问题分析

你的代码存在两个核心问题:

  • 变量类型溢出:18位十六进制数对应72位二进制,远超过long(通常32/64位)的存储范围。比如示例值ec6260d8b431e420d6的十进制值约为1.3×10²¹,而64位无符号整数unsigned long long的最大值仅约1.8×10¹⁹,必然溢出导致结果错误。
  • 十六进制字符转换错误:当前代码仅能正确处理大写A-F,遇到小写a-f时计算出的digit值完全错误,直接导致结果偏差。

解决方案

方案1:使用128位整数类型(GCC/Clang支持)

大多数现代编译器(如GCC、Clang)支持__int128类型,可存储128位整数,完全覆盖18位十六进制数的范围。同时修复字符转换逻辑,兼容大小写输入:

#include <stdio.h>
#include <ctype.h>

// 自定义__int128打印函数,标准库不支持直接输出该类型
void print_int128(unsigned __int128 num) {
    if (num == 0) {
        printf("0");
        return;
    }
    char buf[40];
    int i = 0;
    while (num > 0) {
        buf[i++] = num % 10 + '0';
        num /= 10;
    }
    while (--i >= 0) {
        putchar(buf[i]);
    }
}

int main() {
    char hex[100];
    printf("Enter a hexadecimal number: ");
    scanf("%s", hex);
    // 用无符号128位类型存储转换结果,避免溢出
    unsigned __int128 decimal = 0;
    int i = 0;
    while (hex[i] != '\0') {
        char c = tolower(hex[i]); // 统一转小写,简化判断逻辑
        int digit;
        if (c >= '0' && c <= '9') {
            digit = c - '0';
        } else if (c >= 'a' && c <= 'f') {
            digit = 10 + (c - 'a');
        } else {
            printf("Invalid hex character: %c\n", hex[i]);
            return 1;
        }
        decimal = decimal * 16 + digit;
        i++;
    }
    printf("The decimal equivalent of %s is ", hex);
    print_int128(decimal);
    printf(".\n");
    return 0;
}

方案2:大数字符串模拟(兼容所有编译器)

如果编译器不支持__int128,可以通过字符串模拟十进制数的乘法和加法来处理超大数:

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

// 字符串十进制数乘16
void multiply_by_16(char *num) {
    int len = strlen(num);
    int carry = 0;
    for (int i = len - 1; i >= 0; i--) {
        int digit = (num[i] - '0') * 16 + carry;
        num[i] = digit % 10 + '0';
        carry = digit / 10;
    }
    // 处理进位
    while (carry > 0) {
        memmove(num + 1, num, len + 1);
        num[0] = carry % 10 + '0';
        carry /= 10;
        len++;
    }
}

// 字符串十进制数加digit
void add_digit(char *num, int digit) {
    int len = strlen(num);
    int carry = digit;
    for (int i = len - 1; i >= 0 && carry > 0; i--) {
        int sum = (num[i] - '0') + carry;
        num[i] = sum % 10 + '0';
        carry = sum / 10;
    }
    while (carry > 0) {
        memmove(num + 1, num, len + 1);
        num[0] = carry % 10 + '0';
        carry /= 10;
        len++;
    }
}

int main() {
    char hex[100];
    printf("Enter a hexadecimal number: ");
    scanf("%s", hex);
    // 初始化结果为"0"
    char decimal[40] = "0";
    int i = 0;
    while (hex[i] != '\0') {
        char c = tolower(hex[i]);
        int digit;
        if (c >= '0' && c <= '9') {
            digit = c - '0';
        } else if (c >= 'a' && c <= 'f') {
            digit = 10 + (c - 'a');
        } else {
            printf("Invalid hex character: %c\n", hex[i]);
            return 1;
        }
        multiply_by_16(decimal);
        add_digit(decimal, digit);
        i++;
    }
    printf("The decimal equivalent of %s is %s.\n", hex, decimal);
    return 0;
}

关键修改说明

  • 类型选择:unsigned __int128能容纳最大18位十六进制数(0xFFFFFFFFFFFFFFFFFFFFFFFF),彻底解决溢出问题。
  • 字符处理:用tolower统一转换输入字符,再分别处理数字和字母,确保大小写输入都能正确转换。
  • __int128打印:标准库未提供直接打印支持,手动实现逐位取余逆序输出的函数完成结果打印。

内容的提问来源于stack exchange,提问作者John Fly Martin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 06:53:27