从度到弧度的转换不够准确

  • 本文关键字:不够 转换 c# trigonometry
  • 更新时间 :
  • 英文 :


我非常清楚从度到弧度的转换是如何工作的,但我仍然有问题。问题在于它的准确性。

您可能知道System.Math库中的三角函数使用弧度,但我需要三角函数,您可以在其中插入度数。所以我创建了一个具有CosSinTan函数的Helper类,这些函数只是将度数转换为它们内部的弧度并调用它们的Math函数。

public static class Helper
{
public static double Sin(double degrees) => Math.Sin(degrees * Math.PI / 180.0);
public static double Cos(double degrees) => Math.Cos(degrees * Math.PI / 180.0);
public static double Tan(double degrees) => Math.Tan(degrees * Math.PI / 180.0);
}

但是,例如,当我使用Math.Tan(45)时,它返回 0.999999999989 而不是 1。我的朋友们,我要问你们的问题是,如何使这句话完全准确。

提前谢谢。

编辑: 我知道,会有小错误,不可能摆脱它们。我真正想知道的是如何将值四舍五入所需的金额(不要太多,也不要太少(,以便无论如何它都可以工作。

编辑2: 上下文在这个问题上非常重要,所以这里是:

我需要为具有以下构造函数的Line类进行三角函数:

public Line(Vector2 beginning, Vector2 end)
{
this.beginning = beginning;
this.end = end;
this.direction = 180.0 * Math.Atan(end.Y - beginning.Y / end.X - beginning.X) / Math.PI;
this.slope = Helper.Tan(direction);
this.length = Helper.DistanceBetweenTwoPoints(beginning, end);
this.offset = beginning.X;
}

问题出现在我为斜率分配值的线上,我需要使用线性代数检查点是否在这条线上。

披露:Vector2是一个具有double xdouble y的结构。就这样。

使用双精度时,您总是会遇到舍入错误。这就是浮点运算的本质。Double 可以携带大约 16 个十进制数字。在每个操作中,错误都会累积。"诀窍"是接受这个错误,永远不要将双精度/浮点数与相等进行比较(除非您知道自己在做什么(,并对输出进行有意义的四舍五入。

请参阅 http://floating-point-gui.de/。

要确定一个点是否位于两点之间的直线上或类似问题,您不需要四舍五入,而是使用公差:计算点和线之间的最短距离,并检查它是否低于阈值。这个阈值可以/应该有多大取决于您的应用程序,没有简单的答案。例如,如果您的点在 0..10 范围内,则 1e-7 的公差对我来说是合理的。如果你想要一个通用的实现,你应该采取最大的

  • 点的距离乘以一个因子(例如dist(begin, end) * 1e-8(
  • 非常小距离的绝对值(例如1e-10(

但是您仍然会遇到问题。例如,如果线路从(10000000.1,0)(10000000.2,0),请参阅此处了解详细信息。一般来说,这是一个广泛的话题。

使用您通过Helper.Tan(direction)获得的斜率来计算一个点是否在一条线上,对于不同的斜率会产生不同数量的误差,随着方向接近+/- PI / 2,这些误差会变得更糟,因为随着x接近+/- PI/2tan(x)接近无穷大,并且在+/- PI/2时它根本不会起作用。

要查看点是否靠近线,请使用线的向量和到该点的向量的叉积。例如,线是从点AB点,点是P那么当P在线时Cross(B-A,P-A)将为零。为了消除与线长相关的误差,将叉积除以线长平方,并与任意小公差epsilon进行比较。

// A,B, P are Vector2
double cross = (B.x-A.x) * (P.y-A.y) - (B.y-A.y) * (P.x-A.x);
cross /= (B.x-A.x) * (B.x-A.x) + (B.y-A.y) * (B.y-A.y);
double epsilon = 1.0e-6; // 1 millionths of a unit
if (Math.abs(cross) < epsilon) {
// point P is on line A,B
} 

顺便说一句,Math.PI 是无理数的近似值,无论您使用什么系统,使用它都会引入错误。PI根本不能写成数字。在现实世界中,所有测量都有误差,对于PI 7位的所有实际应用,3.141592的精度绰绰有余。

最新更新