为什么这个浮点数的值会从设置的值改变?

9
为什么这个C程序会给出“错误”的输出?
#include<stdio.h>

void main()
{
    float f = 12345.054321;

    printf("%f", f);

    getch();
}

输出:

12345.054688

但输出应该是12345.054321
我正在使用VS2008中的VC++。
5个回答

11

由于并非所有实数值都可以用浮点数(或双精度浮点数)表示,因此它会给出“错误”的答案。您将得到基于底层编码的近似值。

为了表示每个实数值,即使是在1.0x10-100和1.1x10-100之间这样极小的范围内,你仍需要无限数量的比特位。

单精度IEEE754值只有32位可用(其中一部分被任务分配给其他东西,如指数和NaN/Inf表示),因此不能给您无限精度。它们实际上只有23位可用,可以提供约224的精度(还有一个额外的隐含位),即略大于7个十进制数字(log10(224)大约是7.2)。

我在引号中使用“错误”一词是因为它实际上不是“错误”的。错误的是您对计算机如何表示数字的理解(虽然请不要感到冒犯,您在这种误解方面并不孤单)。

请前往http://www.h-schmidt.net/FloatApplet/IEEE754.html并在“十进制表示”框中输入您的数字,以查看其运作方式。

如果您想要更精确的数字,请使用双精度浮点数-这些数字可用于表示值的位数是单精度浮点数的两倍(假设您的C实现针对浮点和双精度浮点数据类型分别使用IEEE754单精度和双精度)。

如果您想要任意精度,则需要使用“bignum”库,例如GMP,不过这比本机类型慢得多,因此请确保您理解权衡。


2

在您的平台上,十进制数12345.054321不能准确地表示为float。您看到的结果是最接近能够被表示为float的数字的十进制近似值。


我知道这种情况发生在C#中,但从未想到过会在C中出现。 - user366312
C语言的float也是固定精度类型,因此与C#没有区别。 - CB Bailey

2

1

这与精度有关。您的数字在浮点数中无法被准确存储。


真和假 - 运算符的数字不能被准确存储,但浮点数可以精确地存储高精度数字,只要它们在二进制中能够被精确表示即可(例如1/65536)。 - Matt Curtis
2
@Matt,这实际上不是zaf提出的声明,他说:_你的数字_不能... - paxdiablo
好的,已点赞。我只是想明确一下,精度本身并不是浮点数的问题。 - Matt Curtis

0

单精度浮点值只能表示大约八到九个有效数字(十进制)。在此之后,您将看到量化误差。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接