为什么我不能乘以浮动?

时间:2010-06-13 05:00:26

标签: c floating-point floating-accuracy

  

可能重复:
  Dealing with accuracy problems in floating-point numbers

我很惊讶为什么我试图在C中加倍浮点数(使用GCC 3.2)并且它没有像我预期的那样做。作为样本:

int main() {
  float nb = 3.11f;
  nb *= 10;
  printf("%f\n", nb);
}

显示:31.099998

我对浮动的实现方式及其产生这种意外行为的原因感到好奇吗?

6 个答案:

答案 0 :(得分:14)

首先,你可以乘以花车。你遇到的问题不是乘法本身,而是你使用的原始数字。乘法可能会失去一些精确度,但是这里您乘以的原始数字始于精度损失。

这实际上是预期的行为。 float是使用二进制表示实现的,这意味着它们无法准确表示十进制值。

有关详细信息,请参阅MSDN

您还可以在the description of float中看到它有6到7位有效数字。在您的示例中,如果您将31.099998舍入为7位有效数字,则会得到31.1,因此它仍然可以按预期运行。

double类型当然会更准确,但由于它的二进制表示仍然有舍入误差,而你写的数字是十进制的。

如果想要十进制数的完全准确性,则应使用十进制类型。此类型存在于C#等语言中。 http://msdn.microsoft.com/en-us/library/system.decimal.aspx

您还可以使用有理数表示。只要你可以将数字表示为两个整数的除法,就可以使用两个整数来提供完全的准确性。

答案 1 :(得分:5)

这是按预期工作的。计算机具有有限的精度,因为它们试图从整数计算浮点值。这会导致浮点不准确。

Floating point wikipedia页面详细介绍了代表性和由此导致的准确性问题:)

有趣的现实世界的注释:this部分原因是使用整数(美分)进行大量金钱计算 - 不要让计算机因精度不足而亏钱!我想要我的$ 0.00001!

答案 2 :(得分:4)

数字3.11不能用二进制表示。 24位有效位最接近的是11.0001110000101000111101,小数点为3.1099998950958251953125。

如果您的号码3.11应该代表货币金额,那么您需要使用小数表示。

答案 3 :(得分:2)

在Python社区中,我们经常看到有人对此感到惊讶,因此在这个问题上有经过充分测试和调试的FAQstutorial sections(当然,它们是用Python语言表达的) ,而不是C,但由于Python委托浮动算术到底层的C和硬件,所以浮点机制的所有描述仍然适用。)

当然,这不是乘法的错误 - 删除乘以nb的语句,无论如何你都会看到类似的问题。

答案 4 :(得分:1)

来自Wikipedia article

  

浮点数的事实   不能准确地代表所有真实的   数字和那个浮点数   操作无法准确表示   真正的算术运算,导致   许多令人惊讶的情况。这是   与有限精度有关   哪些计算机通常代表   号。

答案 5 :(得分:0)

浮点不精确,因为它们使用基数2(因为它是二进制:0或1)而不是基数10.而基数2转换为基数10,正如之前所说的那样,将导致舍入精度问题。