【问题标题】:Inconsistent results while printing float as integer [duplicate]将浮点数打印为整数时结果不一致[重复]
【发布时间】:2012-10-22 08:00:37
【问题描述】:

可能重复:
print the float value in integer in C language

我正在尝试这样一个相当简单的代码:

float a = 1.5;
printf("%d",a);

它打印出0。但是,对于其他值,例如 1.4、1.21 等,它会打印出一个垃圾值。不仅是 1.5,对于 1.25、1.5、1.75、1.3125(换句话说,可以完美转换为二进制形式的十进制数),它正在打印0。这背后的原因是什么?我发现了一个类似的帖子here,第一个答案看起来很棒,但我看不出来。任何机构都可以解释为什么会这样吗?字节序与 t 有什么关系?

【问题讨论】:

  • 是的,我知道。这是我在问题中提供的链接!
  • 看看浮点数和整数是如何存储在位中的。
  • @Cupidvogel:是的,我知道。你基本上又问了同样的问题,因为你不明白答案。您应该对已接受的答案添加评论,要求澄清。
  • 大多数时候我这样做,人们没有回应。所以我又问了一遍。再加上答案,虽然简洁,但对我来说有点难以理解,因为我是 C 的新手。所以我想我可以做一个详细的解释。
  • 你们为什么总是四处寻找机会来结束问题、删除问题、投反对票等?您是否只是为了能够做到这一点而获得积分?做这些事情会让你有力量感吗?通过负责来尝试维护网站的标准是一回事,即使对 OP 来说非常不方便,也要让其成为你存在的理由是另一回事。

标签: c floating-point integer double endianness


【解决方案1】:

你没有投射浮点数,printf 只是将它解释为一个整数,这就是你得到 看似垃圾值的原因。

编辑:

查看这个示例 C 代码,它显示了 double 是如何存储在内存中的:

int main()
{
    double a = 1.5;
    unsigned char *p = &a;
    int i;

    for (i=0; i<sizeof(double); i++) {
        printf("%.2x", *(p+i));
    }
    printf("\n");
    return 0;
}

如果您使用 1.5 运行它,它会打印出来

000000000000f83f

如果你用 1.41 试试,它会打印出来

b81e85eb51b8f63f

因此,当 printf1.5 解释为 int 时,它会打印零,因为在尝试使用 1.41 时,4 个 LSB 是零和其他值。

话虽如此,这是一种未定义的行为,你应该避免它,而且你不会总是得到相同的结果,这取决于机器和参数的方式通过了。

注意:字节是颠倒的,因为这是在小型印度机器上编译的,这意味着最低有效字节在前。

【讨论】:

  • 这不是垃圾值。对于那些数字,它总是打印一个 0。它背后有一个逻辑,我想明白这一点。
  • @Cupidvogel 我没有说它是垃圾,我说它似乎是因为 printf 试图将 float(或 double)解释为 int,这就是它背后的逻辑
  • 你总是得到相同的垃圾值并不意味着它背后有一些逻辑。只是计算机每次都执行相同的指令。
  • @BoPersson 实际上背后有逻辑,请检查 OP 问题中链接的问题
  • printf 传递带有 double 参数的“%d”规范时,printf 可能会尝试将 something 解释为整数,但您不能依赖它是double 的一部分。在许多实现中,浮点值与整数值在不同的寄存器中传递。因此,当printf 尝试格式化“%d”的参数时,它将使用与double 值完全无关的位。
【解决方案2】:

d 代表:decimal。因此,尽管 a 是浮点数/双精度数/整数/字符,.... 当您使用 : "%d" 时,C 将以十进制打印该数字。所以,如果 a 是整数类型(整数、长整数),没问题。如果 a 是 char :因为 char 是一种整数类型,所以,C 将以 ASCII 格式打印 char 的值。

但是,问题出现了,当a是float类型(float/double)时,只是因为如果a是float类型,C会有特殊的方式来读取这个,而不是十进制方式。所以,你会得到奇怪的结果。

为什么会有这个奇怪的结果?

我只是简单解释一下:在计算机中,实数由两部分表示:exponentmantissa。如果你说:这是一个实数,C 会知道哪个是指数,哪个是尾数。但是,因为你说:嘿,这是整数。指数部分和尾数部分没有区别 -> 奇怪的结果。

如果您想准确理解,如何知道它将打印哪个整数(当然,您可以猜到)。你可以访问这个链接:represent FLOAT number in memory in C

如果你不想得到这个奇怪的结果,你可以将int 转换为浮点数,这样,它就会打印浮点数的整数部分。

 float a = 1.5;
   printf("%d",(int)a);

希望有帮助:)

【讨论】:

  • 我已经编辑了一些部分。希望这对你有帮助:)
【解决方案3】:

printf 中的参数不匹配是undefined beahivour 类型转换a 或使用%f

这样用

printf("%d",(int)a);

printf("%f",a);

【讨论】:

    【解决方案4】:

    你不关心参数提升。因为printf 是一个可变参数函数,所以参数被提升:

    C11 (n1570),第 6.5.2.2 节函数调用
    具有浮点类型的参数被提升为双精度。

    所以printf 尝试将您的double 变量解释为整数类型。它会导致未定义的行为。只需添加演员表:

    double a = 1.5;
    printf("%d", (int)a);
    

    【讨论】:

    • 好的,它被提升为双倍。然后会发生什么?
    • 断言printf 试图将double 变量解释为整数类型是不正确的。实际行为取决于实现。通常,double 在与传递整数的位置完全不同的寄存器中传递。当printf 尝试读取整数参数时,它会读取希望找到整数参数的寄存器。该寄存器的内容可能与double 的值完全无关。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-22
    • 2021-02-02
    • 1970-01-01
    相关资源
    最近更新 更多