Math.Cos & Math.Sin in C#

半腔热情 提交于 2019-11-29 13:31:29

Let me answer your question with another one: How far do you think 6.12303176911189E-17 is from 0? What you call deviance is actually due to the way floating point numbers are internally stored. I would recommend you reading the following article. In .NET they are stored using the IEEE 754 standard.

See answers above. Remember that 6.12303176911189E-17 is 0.00000000000000006 (I may have even missed a zero there!) so it is a very, very small deviation.

Read up on floating point arithmetic. It is never and can never be exact. Never compare exactly to anything, but check whether the numbers differ by a (small) epsilon.

KAI

Since the result of the calculation is really close to 0 (zero), you could just use rounding:

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

So, calculation of sin/cos from radian:

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

Which if yourRadianValue = 90, returns sin = 1 and cos = 0.

The other posts are correct about the practical matter of working with floating point implementations which return results with small errors. However, it would be nice if floating point library implementations would preserve the basic identity of well-known functions:

Math.Sin(Math.PI) should equal 0,
Math.Cos(Math.PI) should equal -1,
Math.Sin(Math.PI/2) should equal 1,
Math.Cos(Math.PI/2) should equal 0, etc.

You would expect that a floating point library would respect these and other trigonometric identities, whatever the minor errors in its constant values (e.g. Math.PI).

The fact that you're getting a small error from Math.Cos(Math.PI/2) indicates that the implementation is calculating the result, rather than pulling it from a table. A better implementation of Math.Cos and the other transcendental functions could be more accurate for specific identities.

I'm sure in the case of C#, this behavior is expected, and so Microsoft couldn't change it without affecting existing code. If getting the precise result for specific trigonometric identities matters to you, you might wrap the native floating point functions with some code that checks for well-known inputs.

you should use rounding

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

the result would be: sin: 1 cos: 0

As noticed by @b1tw153, it'd be great if exact values were returned for multiples of PI/2. And that's exactly what Microsoft did in their System.Numerics library; if you examine the source code for Matrix3x2.CreateRotation, you'll note they handle n * PI/2 cases manually: https://github.com/Microsoft/referencesource/blob/master/System.Numerics/System/Numerics/Matrix3x2.cs#L325

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!