在C#

时间:2016-01-21 14:47:59

标签: c# algorithm math trigonometry

这是一个使用来自this blog的泰勒级数逼近反正弦(x)的公式 enter image description here

这是我在C#中的实现,我不知道哪里出错了,运行时代码给出了错误的结果: 当i = 0时,除法将为1 / x。所以我在启动时分配temp = 1 / x。对于每次迭代,我在“i”之后改变“temp”。 我使用连续循环,直到下一个两个值非常“接近”在一起。当两个下一个数字的增量非常小时,我将返回该值。

我的测试用例: 输入为x = 1,因此除了arcsin(X)将是arcsin(1)= PI / 2 = 1.57079633 rad。

class Arc{
            static double abs(double x)
            {
                return x >= 0 ? x : -x;
            }

            static double pow(double mu, long n)
            {
                double kq = mu;
                for(long i = 2; i<= n; i++)
                {
                    kq *= mu;
                }
                return kq;
            }

            static long  fact(long n)
            {
                long gt = 1;
                for (long i = 2; i <= n; i++) {
                    gt *= i;
                }
                return gt;
            }


            #region arcsin
            static double arcsinX(double x) {
              int i = 0;
              double temp = 0;
              while (true)
               {
               //i++;
               var iFactSquare = fact(i) * fact(i);
               var tempNew = (double)fact(2 * i) / (pow(4, i) * iFactSquare * (2*i+1)) * pow(x, 2 * i + 1) ;
            if (abs(tempNew - temp) < 0.00000001)
            {
                return tempNew;
            }
            temp = tempNew;
            i++;
        }
    }

            public static void Main(){
                Console.WriteLine(arcsin());
                Console.ReadLine();
            }
        }   

3 个答案:

答案 0 :(得分:4)

在许多系列评估中,使用术语之间的商来更新术语通常很方便。这里的商是

                (2n)!*x^(2n+1)       4^(n-1)*((n-1)!)^2*(2n-1)
a[n]/a[n-1] = ------------------- * --------------------- -------
              (4^n*(n!)^2*(2n+1))       (2n-2)!*x^(2n-1)  

  =(2n(2n-1)²x²)/(4n²(2n+1)) 
  = ((2n-1)²x²)/(2n(2n+1))

因此,计算序列值的循环是

sum = 1;
term = 1;
n=1;
while(1 != 1+term) {
    term *= (n-0.5)*(n-0.5)*x*x/(n*(n+0.5));
    sum += term;
    n += 1;
}
return x*sum;

abs(x)<1保证收敛,对于x=1的评估,您必须采用角度减半,这通常是加速收敛的好主意。

答案 1 :(得分:3)

您正在保存两个不同的临时值(temp和tempNew)以检查继续计算是否无关紧要。这很好,除了你没有保存这两个值的总和。

这是一个总结。您需要将每个新计算值添加到总计中。您只跟踪最近计算的值。您只能返回系列的最后一个计算值。所以你总会得到一个非常小的数字作为你的结果。将其转换为总和,问题应该消失。

答案 2 :(得分:2)

注意:我已经将此作为社区维基的答案,因为我不是第一个想到这一点的人(只是第一个将其记在评论中)。如果您觉得需要添加更多内容才能完成答案,只需在其中进行编辑即可!

普遍怀疑这是Integer Overflow,即您的一个值(可能是fact()iFactSquare()的回报)对于您选择的类型来说太大了。由于您使用的是签名类型,因此它会变为负数 - 当它变为过大的正数时,它会循环回到负数。

尝试跟踪计算过程中n的大小,并确定如果您通过factpow和{{1}运行该数字,它会给您带来多大的数字}} 功能。如果它比我们想象的Maximum long value in 64-bit更大(假设您使用的是64位,那么对于32位来说它会小得多),那么请尝试使用{{ 3}}