昨天我问了一个浮点问题,我还有一个问题。我正在做一些计算,我使用 math.h(C 语言)正弦、余弦和正切函数的结果。
其中一位开发人员喃喃地说,您必须小心这些函数的返回值,我不应该对 gcc 数学函数的返回值做出假设。我不想开始讨论,但我真的想知道在使用标准数学函数进行计算时需要注意什么。
X
昨天我问了一个浮点问题,我还有一个问题。我正在做一些计算,我使用 math.h(C 语言)正弦、余弦和正切函数的结果。
其中一位开发人员喃喃地说,您必须小心这些函数的返回值,我不应该对 gcc 数学函数的返回值做出假设。我不想开始讨论,但我真的想知道在使用标准数学函数进行计算时需要注意什么。
X
您不应假设返回的值在不同的编译器/stdlib 版本之间会保持高精度。
就是这样。
例如,您不应期望 sin(PI/6) 等于 cos(PI/3)。你也不应该期望 asin(sin(x)) 等于 x,即使 x 在 sin 的域中。它们将接近,但可能不相等。
浮点数很简单。请始终记住,所有浮点运算和函数都存在不确定性。它通常被建模为随机的,即使它通常不是,但如果你把它当作随机的,你将成功地理解你自己的代码。例如:
a=a/3*3;
这应该被视为:
a=(a/3+error1)*3+error2;
如果您想估计错误的大小,则需要深入研究每个操作/功能以找出答案。不同的编译器、参数选择等会产生不同的值。例如,0.09-0.089999 在具有 5 位精度的系统上会产生介于 -0.000001 和 0.000001 之间的错误。这个误差的大小与实际结果相当。
如果您想学习如何尽可能精确地进行浮点运算,那么这是它自己的研究。
问题不在于标准数学函数,而在于浮点运算的性质。
非常简短的版本:不要比较两个浮点数是否相等,即使是像10 == 10 / 3.0 * 3.0
or这样的明显、琐碎的身份tan(x) == sin(x) / cos(x)
。
你应该注意精度:
同意所有关于你不应该比较平等的回答。但是,您可以做的是检查数字是否足够接近,如下所示:
if (abs(numberA - numberB) < CLOSE_ENOUGH)
{
// Equal for all intents and purposes
}
哪里CLOSE_ENOUGH
是一些适当小的浮点值。