浮点再次

昨天我问了一个浮点问题,我有另一个问题。 我正在做一些计算,我使用math.h(C语言)正弦,余弦和正切函数的结果。

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

X

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

就是这样。

例如,你不应该期望sin(PI / 6)等于cos(PI / 3)。 你也不应该期望asin(sin(x))等于x,即使x在sin的域中也是如此。 他们会很接近,但可能不平等。

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

A = A / 3 * 3;

这应该被视为:

α=(A / 3 + ERROR1)* 3 +误差2;

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

如果你想学习如何使浮点精确到可行,那么它就是它自己的研究。

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

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

你应该注意精度:

  • 浮点数的结构
  • 你是32位,64位平台吗?
  • 你应该阅读IEEE二进制浮点运算标准
  • 有一些有趣的库,如GMP或MPFR。
  • 你应该学习如何比较浮点数
  • 等……

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

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

CLOSE_ENOUGH是一些适当小的浮点值。