Math.Cos& C#中的Math.Sin

时间:2011-05-21 15:14:19

标签: c# trigonometry cosine sine

我正在尝试一些我认为应该相当简单的事情。我有一个角度,一个位置和一个距离,我想从这些信息中找到X,Y坐标。

使用90度的示例输入,我使用以下代码将值转换为弧度:

public double DegreeToRadian(float angle)
{
  return Math.PI * angle / 180.0;
}

这给了我1.5707963267949弧度 然后当我使用

Math.Cos(radians)

我得到了一个答案:6.12303176911189E-17

到底发生了什么事? 90度的余弦应该是0,所以为什么我会得到这样的偏差......更重要的是我怎么能阻止它呢?

7 个答案:

答案 0 :(得分:14)

让我用另一个回答你的问题:你认为6.12303176911189E-17从0开始有多远?您所谓的 deviance 实际上是由于浮点数在内部存储的方式。我建议你阅读following article。在.NET中,它们使用IEEE 754 standard存储。

答案 1 :(得分:6)

见上面的答案。请记住,6.12303176911189E-17是0.00000000000000006(我可能甚至错过了零!)所以这是一个非常非常小的偏差。

答案 2 :(得分:2)

阅读floating point arithmetic。它永远也永远不会是精确的。永远不要与任何东西完全比较,但要检查数字是否因(小)epsilon而不同。

答案 3 :(得分:1)

由于计算结果非常接近0(零),您可以使用舍入:

Math.Round(result, 4): // 4 decimals, e.g.: 2.1234

所以,从弧度计算sin / cos

const double Deg = Math.PI / 180;
double sin = Math.Round(Math.Sin(yourRadianValue * Deg), 4);
double cos = Math.Round(Math.Cos(yourRadianValue * Deg), 4); // 0.0000...06 becomes 0

如果yourRadianValue = 90,则返回sin = 1cos = 0

答案 4 :(得分:1)

其他帖子对于使用浮点实现的实际问题是正确的,这些实现返回了具有小错误的结果。但是,如果浮点库实现保留了众所周知的函数的基本身份,那将是很好的:

Math.Sin(Math.PI) 等于0
Math.Cos(Math.PI) 等于-1
Math.Sin(Math.PI/2) 等于1
Math.Cos(Math.PI/2) 等于0等。

您会期望浮点库会尊重这些和其他trigonometric identities,无论其常量值中的小错误(例如Math.PI)。

您从Math.Cos(Math.PI/2)收到一个小错误的事实表明该实现正在计算结果,而不是从表中提取它。 Math.Cos和其他超越函数的更好实现对于特定身份可能更准确。

我确信在C#的情况下,这种行为是预期的,因此Microsoft无法在不影响现有代码的情况下对其进行更改。如果获得特定三角标识的精确结果对您很重要,您可以使用一些检查已知输入的代码来包装本机浮点函数。

答案 5 :(得分:1)

您应该使用四舍五入

var radians = Math.PI * degres / 180.0;
var cos = Math.Round(Math.Cos(radians), 2);
var sin = Math.Round(Math.Sin(radians), 2);

结果将是: 罪恶:1 cos:0

答案 6 :(得分:0)

@ b1tw153注意到,如果为PI / 2的倍数返回准确的值,那就太好了。 这正是Microsoft在其System.Numerics库中所做的;如果您检查Matrix3x2.CreateRotation的源代码,则会注意到它们手动处理了n * PI / 2种情况:https://github.com/Microsoft/referencesource/blob/master/System.Numerics/System/Numerics/Matrix3x2.cs#L325