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 = 1
和cos = 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无法在不影响现有代码的情况下对其进行更改。 如果获得特定三角标识的精确结果对您很重要,则可以使用一些检查已知输入的代码来包装本机浮点函数。