C float初始化结果意外

时间:2019-04-19 13:53:02

标签: c floating-point initialization

Visual Studio 2019社区 float变量不是我初始化的对象。 为了避免截断,我降低了精确度。 这不是“可控的”吗?

试图以其他方式强制初始化

int main()
{
    // where did my 6 go?
    float b = 80.123456F;
    printf("b:[%f]\n", b);

    // rounds up
    float c = 80.1234569F;
    printf("c:[%f]\n", c);

    // rounds up
    float d = 80.1234561F;
    printf("d:[%f]\n", d);


    // appends a 1
    float e = 80.12345F;
    printf("e:[%f]\n", e);

    // prints what's initialized
    float f = 80.123451F;
    printf("f:[%f]\n", f);

    // prints what's initialized
    float g = 80.123459F;
    printf("g:[%f]\n", g);
}
b:[80.123459]
c:[80.123459]
d:[80.123459]
e:[80.123451]
f:[80.123451]
g:[80.123459]

我从调试器开始,并写了它以满足SO的要求。 就我而言,调试器匹配打印件

3 个答案:

答案 0 :(得分:0)

浮点数最多只能精确到7个有效数字。不是7个十进制数字。 80.123456F有8位有效数字,所以这是行不通的。

80.12345只有7位有效数字,而实际上以80.1234512329101562结尾。只要您不尝试打印超出位数的数字,就可以了。不幸的是,%f总是在小数点后输出6位数字。在这种情况下,这不仅仅具有道理。您可以使用%g稍好一些,在那里您可以指定有效位数。

答案 1 :(得分:0)

两个问题:

    使用printf转换说明符的
  • %f对其舍入的浮点值进行舍入以显示。您可以使用精度说明符控制显示小数点后的位数:printf( "%.8f\n", b );将在小数点后最多显示8位数字,而printf( "%.16f\n", a);将打印16位。不要相信显示的数字值,但是,因为...

  • 无限数量的实数值不能容纳有限数量的位,因此大多数实数值不能精确表示为 -您得到的近似值仅适用于这么多的十进制数字。单精度float类型的精度不能保证超过6到7个小数位数(不仅仅是小数点后的位数,而是总位数)。 double为您提供10到11位数字。如果您需要用许多位数(大于12左右)表示值,则需要超越本机浮点类型并使用第三方多精度库。

答案 2 :(得分:0)

解决此问题的方法可能是更改数据类型。即使double的操作方式与float相同,并通过有限的一组有理数近似大范围的实数,但双精度值是如此接近,以至于舍入误差不太可能发生。

例如,最接近实数80.123456的float值是80.12345123291015625和80.1234588623046875。最接近80.123456的double值是80.123456000000004451067070476710796356201171875和80.1234559999999902902123123747747070789337158203125。

float确实有它的用途,在您要处理大量非常低的精度数字集的情况下,但是double是更有用的类型。使用double将物理量输入程序时,测量误差将超过舍入误差。