C#中的Math.Cos和Math.Sin

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

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

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

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

 Math.Cos(radians) 

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

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

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

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

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

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

 Math.Round(result, 4): // 4 decimals, eg: 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

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

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

您可以预期浮点库会尊重这些和其他三角恒等式 ,无论其常量值中的微小错误如何(例如Math.PI)。

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

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