C# – 为什么Math.Atan(Math.Tan(x))!= x?

请问这个新手问题……

如果tan(x)= y且atan(y)= x为什么Math.Atan(Math.Tan(x))!= x ??

我试图计算x之类的东西

tan(2/x +3) = 5 

所以

 atan(tan(2/x + 3) = atan(5) 

等等…但我试过这个:

 double d = Math.Atan(Math.Tan(10)); 

和d!= 10 ……为什么?

谢谢你的时间!

  1. 切线函数是周期性的周期pi,并且只有当您将其限制为其域内的子集时才是可逆的。 通常这种集合的选择是开放区间] -pi / 2,pi / 2 [,因此arctan函数将始终返回该区间中的一个点。 在你的情况下,10 = 3 * pi + 0.57522 ……因此,10的正切的arctan将返回0.57522 ……
  2. 注意,如上定义的arctan函数是单射的并且在所有实数上定义,因此与您的问题相反
     math.tan(math.atan(x)) == x 

    确实适用于每个x(数值误差除外)。

  3. 为了处理数值错误,您不应该使用==或!=在浮点计算的结果之间进行比较。 使用
     abs(number1 - number2) < epsilon // == abs(number1 - number2) >= epsilon // != 

    相反,epsilon是一个小的正常数。

图表可能有助于解释您未获得预期结果的原因。

替代文字http://sofzh.miximages.com/c%23/Tangent_701.gif

http://mathworld.wolfram.com/Tangent.html

这显示了Tan的图形,但是如果你想象为给定的y读取x的值(例如y = 0),那么根据你读的Tan的“strand”,你会得到一个不同的答案(-pi, 0,pi …)。 这就是Arctan(x)有多个解决方案的观点。

如果arctan仅限于其中一条链,例如-pi / 2

编辑:但是,根据http://msdn.microsoft.com/en-us/library/system.math.atan.aspx ,如果输入,atan方法已经返回-pi / 2

编辑(FR):增加数字

我不知道任何C#,但是数学表明tan不能反转,只能在一个小的intervall中。

例如,tan(pi)= 0并且tan(0)= 0.当要求atan(0)时,它可以是0或pi(或pi的每个倍数),因此结果在-pi / 2的范围内。 Pi / 2相。

即使你在可反转范围内以x开始,我也不必工作,因为浮点的舍入误差(它没有无限制的精度)。

tan -1 (tan(x))== x表示(-PI / 2,PI / 2)中的所有x。

  1. 由于切线函数是周期性的,我们需要对输入角度进行归一化。 Math.Atan返回一个以弧度为单位测量的角度θ ,使得-π/ 2≤θ≤π / 2 ,因此归一化到该范围是有意义的(因为它显然不会在该范围内的任何内容):

     double normalizedAngle = (angle + Math.PI / 2) % Math.PI - Math.PI / 2; 
  2. 应将双打与一些误差范围进行比较。 但事实上,对于这种情况, Double.Epsilon太小了“如果你创建一个自定义算法来确定两个浮点数是否可以被认为是相等的,你必须使用一个大于Epsilon常数的值来建立可接受的绝对值两个值的差异边际被认为是相等的。(通常,差异的差异比Epsilon大很多倍。)“例如, Math.Atan(Math.Tan(-0.49999632679501449)) + 0.49999632679501449将大于Double.Epsilon1.1235582092889474E+307次。

如果您发布了您要完成的任务,那么它可能会有所帮助。 例如,当我尝试使用角度时,如果输入的象限对我来说,我有发现处理问题的触发函数的回忆。

通常,当您处理浮点数时,您正在处理近似值。 有些数字无法准确表示,而tan和arctan操作本身只是近似的。

如果你想比较浮点数,你需要问它们是否几乎相等,或等价,如果差值小于某个小值,并仔细考虑你在做什么。

这里有一些常见问题解答(对于c ++,但想法是一样的),稍微谈谈一些浮点数的奇怪之处:

常见问题29.16
常见问题29.17
常见问题29.18

编辑:看看其他答案,我意识到主要问题可能是tan不可逆,但每当你测试浮点数是否相等时,近似问题也值得考虑。

查看Math.Atan的.net文档,atan产生的值介于-π/ 2和≤π / 2之间,不包括10.我认为是arctan的通常范围。

double d = Math.Atan(1)*(180 / Math.PI); 所以d将是45度