有没有办法不损失精度并仍然获得价值?

Is there any way to not lose the precision and still get the value?

提问人:Dipanshu 提问时间:10/19/2021 最后编辑:463035818_is_not_an_aiDipanshu 更新时间:10/19/2021 访问量:815

问:

首先,我是 C 语言的初学者,之前有 Java 和 Python 编程的经验。该程序的目标是添加 2 个数字。当我在玩代码时,我遇到了精度问题。当我添加 2 个数字时,出现了这个问题 - 1 个是浮点数据类型,另一个是双精度数据类型。

法典:

#include <stdio.h>

int main() {
    double b=20.12345678;
    float c=30.1234f;
    printf("The Sum of %.8f and %.4f is= %.8f\n", b, c, b+c);
    return 0;
}

输出:

20.12345678 和 30.1234 的总和是 = 50.24685651

但是,正确的输出应为:50.24685678

浮点值精确到小数点后 6 位,输出也是如此。 我尝试将值显式转换为双精度类型,但它仍然没有用。

PS:当我将变量类型从 float 转换为 double 时,输出是精确的;但是有没有其他方法可以在不弄乱其数据类型的情况下添加浮点数和双精度整数? 谢谢。

c 浮精度

评论

3赞 yano 10/19/2021
即使这样,你也会发现不精确。有无限数量的数字,但您的计算机资源有限。请参阅浮点数学坏了吗?double
0赞 user786 10/19/2021
我认为这可以通过移动位并将精度存储在单独的变量中来完成
1赞 Steve Summit 10/20/2021
有两件事你必须记住。浮点数(和双精度)不仅精度有限,而且它们在内部使用二进制,而不是十进制。所以当你说 时,你不会得到 30.1234000000 in ,很明显它在 6 位数字之后干净利落地切断了。不,你得到的是一个二进制数,它在 24 后干净利落地切断。在二进制中,这个数字是 ,在十六进制中是 。如果将其转换为十进制,则相当于 30.1233997344970703125,这就解释了为什么当您将其添加到它时,可能会将最后的 678 更改为 651。float c=30.1234fc0b11110.00011111100101110010x1E.1F972b

答:

2赞 dbush 10/19/2021 #1

赋值无法准确表示,因此会为其赋值下一个最接近的值。打印到小数点后 4 位时看不到,但打印 8 位时会看到它:c

printf("The Sum of %.8f and %.8f is= %.8f\n", b, c, b+c);

输出:

The Sum of 20.12345678 and 30.12339973 is= 50.24685651

因此,对于您尝试进行的计算来说,常数已经不够精确。30.1234f

2赞 John Bode 10/19/2021 #2

float仅保证 6 位十进制数字的精度,因此任何使用 a 的计算(即使其他操作数是 ,即使您将结果存储到 a )也只能精确到 6 位。floatdoubledouble

如果您需要更高的精度,请将自己限制为 或 。如果需要超过 10 个十进制数字的精度,则需要使用本机浮点类型和库函数以外的其他方法。你要么需要自己滚动,要么使用任意精度的数学库,如GNU MP。doublelong double

评论

0赞 Eric Postpischil 10/20/2021
float“保证”六位数仅在非常有限的意义上。这种粗暴的陈述不应该被教授,因为它助长了误解。值得注意的是,从中得出的结论是“所以......将只有精确的 6 位数字“是不正确的。