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

32位IEEE754浮点数转十进制程序报错:输出-nan求助

32位IEEE754浮点数转十进制程序错误排查与修复

问题描述

实现将32位IEEE754浮点数的命令行参数转换为十进制浮点数的C程序时,测试输入./f32 00111111100000000000000000000000,程序输出-nan,无法得到正确结果(预期输出应为1.0000)。

原代码如下:

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

int main(int argc, char *argv[]) {
    (void)argc;

    // variables
    long signBit;
    long expVal = 0;
    double mantissa = 0.0;

    int expCounter = 0;
    int fracCounter = -1;

    char numString[33];
    char expBits[9];
    char fracBits[24];
    int len = strlen(argv[1]);

    for (int i = 1; i < len; i++) {
        numString[i - 1] = argv[1][i];
    }

    // sets signBit equal to first index from cl argument
    signBit = strtol(&argv[1][0], NULL, 10);
    strncpy(expBits, numString + 1, 7);
    strncpy(fracBits, numString + 9, 23);

    for (int i = 0; i < 7; i++) {
        long bitVal = strtol(&expBits[i - 1], NULL, 10);

        // calculates e
        expVal += (bitVal * (long)pow(2, expCounter));
        expCounter++;
    }

    expVal -= 127; // adjusts expVal for bias

    for (int i = 0; i < 31; i++) {
        int fracVal = (fracBits[i] == '1') ? 1 : 0;

        // calculates mantissa
        mantissa += (fracVal * pow(2, fracCounter));
        fracCounter--;
    }

    // convert to float in base 10
    double float_value = (pow(-1, signBit)) * (1 + mantissa) * (pow(2, expVal));

    printf("%.4f\n", float_value);
    printf("\n");

    return EXIT_SUCCESS;
}

作业要求

In f32.c, write a program that takes a 32-bit IEEE754 representation
of a float as a command-line argument and outputs the float it
represents in base-10.

To account for floating-point error, when printing the float, use
printf("%.4f\n", float_value) to print to 4 decimal places.

These libraries should be useful:

string.h argv[1] is a string. You are allowed to use string.h

You do not have to convert the exponent bits to a base-10 integer
yourself. Please use strtol to convert the exponent bits (const char*) to long. Pass NULL as the second argument. You may use
strlen to get the length of a string. You may use strncpy to
extract the exponent bits and mantissa bits from the 32-bit string. It
can be used similarly to slicing in Python (str[start:end]) or
Java's substring(begIndex, endIndex) method.

math.h Please do not implement exponentiation yourself. For
exponentiation, use pow

错误排查

  1. strtol进制参数错误:原代码中用strtol转换指数位时使用了十进制(base=10),但指数位是二进制字符串,应该指定base=2,这会导致指数值计算完全错误,是输出NaN的核心原因。
  2. 字符串提取错误:
    • 指数位应该提取8位(IEEE754单精度的指数位长度),原代码只复制了7位,且未手动添加字符串终止符\0,导致strtol读取越界。
    • 尾数位提取的起始位置错误,且循环跑了31次(远超23位的长度),访问数组越界内存,得到随机值。
  3. 数组越界访问:计算指数位的循环中,i=0时&expBits[i-1]指向expBits[-1],属于非法内存访问,获取到无效值。
  4. 冗余的numString数组:原代码复制原字符串到numString但未添加终止符,后续操作容易引发未定义行为,且完全没必要,直接操作原字符串即可。

修复后的代码

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

int main(int argc, char *argv[]) {
    // 参数合法性检查:确保输入是32位字符串
    if (argc != 2 || strlen(argv[1]) != 32) {
        fprintf(stderr, "Usage: %s <32-bit IEEE754 string>\n", argv[0]);
        return EXIT_FAILURE;
    }

    // 提取符号位:第1位(索引0)
    long signBit = strtol(&argv[1][0], NULL, 10);

    // 提取指数位:第2-9位(索引1-8),共8位,手动添加终止符
    char expBits[9];
    strncpy(expBits, &argv[1][1], 8);
    expBits[8] = '\0';
    // 二进制转十进制,再减去偏移量127
    long expVal = strtol(expBits, NULL, 2);
    expVal -= 127;

    // 提取尾数位:第10-32位(索引9-31),共23位,手动添加终止符
    char fracBits[24];
    strncpy(fracBits, &argv[1][9], 23);
    fracBits[23] = '\0';

    // 计算尾数值
    double mantissa = 0.0;
    for (int i = 0; i < 23; i++) {
        if (fracBits[i] == '1') {
            mantissa += pow(2, -(i + 1));
        }
    }

    // 计算最终浮点数
    double float_value = pow(-1, signBit) * (1 + mantissa) * pow(2, expVal);

    printf("%.4f\n", float_value);
    return EXIT_SUCCESS;
}

关键修改说明

  • 添加参数合法性检查,避免非法输入。
  • 修正strtol的进制参数为2,正确转换二进制指数位。
  • 正确提取指数位和尾数位,手动添加字符串终止符,避免越界读取。
  • 尾数位循环限制为23次,只计算有效位,避免内存越界。
  • 移除冗余的numString数组,直接操作原命令行参数字符串,减少错误点。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 04:33:12