C 又是浮点数

C 又是浮点数,c,floating-point,math.h,C,Floating Point,Math.h,昨天我问了一个浮点问题,我还有一个。我使用math.h(C语言)正弦、余弦和切线函数的结果进行计算 一位开发人员咕哝道,您必须小心这些函数的返回值,我不应该对gcc数学函数的返回值进行假设。我不想开始讨论,但我真的想知道在使用标准数学函数进行计算时需要注意什么 x您不应该假设返回的值在不同的编译器/stdlib版本之间在高精度上是一致的 这就是问题所在。问题不在于标准的数学函数,而在于浮点运算的本质 非常简短的版本:不要比较两个浮点数是否相等,即使有明显的、琐碎的标识,如10==10/3.0*3

昨天我问了一个浮点问题,我还有一个。我使用math.h(C语言)正弦、余弦和切线函数的结果进行计算

一位开发人员咕哝道,您必须小心这些函数的返回值,我不应该对gcc数学函数的返回值进行假设。我不想开始讨论,但我真的想知道在使用标准数学函数进行计算时需要注意什么


x

您不应该假设返回的值在不同的编译器/stdlib版本之间在高精度上是一致的


这就是问题所在。

问题不在于标准的数学函数,而在于浮点运算的本质


非常简短的版本:不要比较两个浮点数是否相等,即使有明显的、琐碎的标识,如
10==10/3.0*3.0
tan(x)=sin(x)/cos(x)

浮点数很简单。只要记住,所有浮点运算和函数都有一个不确定性组件。它通常被建模为随机的,即使它通常不是随机的,但如果您将其视为随机的,您将成功地理解您自己的代码。例如:

a=a/3*3

应将其视为:

a=(a/3+错误1)*3+错误2

如果您想要估计错误的大小,则需要深入研究每个操作/函数以找出错误。不同的编译器、参数选择等将产生不同的值。例如,在精度为5位的系统上,0.09-0.089999将产生介于-0.000001和0.000001之间的误差。该误差的大小与实际结果相当


如果您想学习如何尽可能精确地进行浮点运算,那么这是它自己的研究。

例如,您不应该期望sin(PI/6)等于cos(PI/3)。也不应该期望asin(sin(x))等于x,即使x在sin的域中。它们很接近,但可能不相等。

您应该注意精度:

  • 浮点数的结构
  • 您是否在32位、64位平台上
  • 你应该读书
  • 有一些有趣的库,如GMP或MPFR
  • 您应该学习如何比较浮点数
  • 等等

同意所有的回答,即不应进行平等比较。但是,您可以做的是检查数字是否足够接近,如下所示:

if (abs(numberA - numberB) < CLOSE_ENOUGH)
{
  // Equal for all intents and purposes
}
if(abs(numberA-numberB)

其中
CLOSE\u ough
是一个适当小的浮点值。

您已经创建了两个帐户。您之前的问题是使用。电子邮件team@stackoverflow.com关于合并它们。不完全回答您的问题,但是如果您使用gcc,您可以尝试使用-mfpmath=sse标志来减少一些浮点错误。这就是我记得说过的。所以,如果我想要更高的精确度,我会使用另一个数学库吗?哪一个?xi如果您希望确保不同的编译器提供完全相同的值,那么您应该使用自己的sin/cos/tan函数,而不是使用供应商提供的stdlib函数。或者使用执行此操作的第三方库。当然,这些函数不能调用其他stdlib例程。或者,您可以生成一组存储为数据文件的trig表,并且您的sin/trig/cos例程将是查找。我想问,这是否真的有必要?这是我过去不得不做的事情,但这肯定不常见。你自己做没有什么意义。Netlib是相当标准的,您自己的滚动将是免费的。有很多非常好的libm是免费提供的,如果你想在你的项目中使用libm,没有理由不使用它们。如果您需要跨平台的按位可复制结果,您最好的选择可能是crlibm,它提供正确的四舍五入结果,但要遵守有关编译器的一些基本假设。不仅它从来都不是随机的,而且您的答案确实没有提供任何有价值的信息。这是大学教授的方法,如果你学习数值分析,它基本上是计算机上浮点运算的数学。音频工程师不会称之为随机值,他们会称之为“噪音”,但这是相同的想法。我的文章提供了一些信息,使程序员能够理解浮点代码中的错误发生在哪里,以及错误有多大。通过将随机值的大小与编译器的选择联系起来,原始问题得到了回答。在IEEE-754环境中,浮点值没有任何随机性。浮点不是黑魔法。舍入的存在并不意味着非确定性。任何特定的浮点计算实际上都不是随机的。然而,误差很难预测,而且由于它们随输入的不同而变化,因此通常很难对它们说任何有用和确定的东西。因此,将其建模为随机变量是有用的。类似地,尽管几乎可以肯定的是,如果给定足够的信息,可以预测骰子滚动,但考虑随机性通常更有用。@史蒂芬和戴维:如果在一个系统中计算2/2.1,精度为15位,那么计算中的误差是什么?我会说1e-15和-1e-15之间有某种未指定的值。可能是零,可能是负,可能是1e-15。我不知道。对我来说,这只是一个小的随机数。我可以做一些调查并找出答案,但通常我不会这么做。我只是假设-1e-15和1e15之间有一个错误。