数学.Cos & C# 中的 Math.Sin

发布于 2024-11-09 01:37:08 字数 396 浏览 2 评论 0原文

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

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

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

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

Math.Cos(radians)

,我最终得到的答案是:6.12303176911189E-17

到底发生了什么? 90 度的余弦应该是 0,那么为什么我会出现这样的偏差......更重要的是我怎样才能阻止它?

I'm trying something that I thought should be reasonably simple. I have an angle, a position and a distance and I want to find the X,Y co-ordinates from this information.

With an example input of 90 degrees I convert the value to radians with the following code:

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

This gives me 1.5707963267949 radians
Then when I use

Math.Cos(radians)

I end up with an an answer of: 6.12303176911189E-17

What the heck is going on? The cosine of 90 degrees should be 0, so why am I getting such a deviance... and more importantly how can I stop it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

匿名的好友 2024-11-16 01:37:08

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

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.

琴流音 2024-11-16 01:37:08

请参阅上面的答案。请记住,6.12303176911189E-17 是 0.00000000000000006(我什至可能漏掉了一个零!),所以这是一个非常非常小的偏差。

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.

肤浅与狂妄 2024-11-16 01:37:08

您应该使用舍入,

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

结果将是:
罪恶:1
因数:0

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

浅听莫相离 2024-11-16 01:37:08

阅读浮点运算。它从来都不是、也不可能是准确的。切勿与任何内容进行精确比较,而是检查数字是否存在(小)epsilon 差异。

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.

魔法少女 2024-11-16 01:37:08

其他帖子关于使用浮点实现的实际问题是正确的,该实现返回带有小错误的结果。但是,如果浮点库实现能够保留众所周知函数的基本标识,那就太好了:

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

您会期望浮点库会尊重这些和其他三角恒等式,无论其常数值有多大误差(例如数学.PI)。

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

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

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.

倾城花音 2024-11-16 01:37:08

正如 @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

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

因为看清所以看轻 2024-11-16 01:37:08

由于计算结果非常接近 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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文