C# 这个C语言中的反正弦近似的实现有什么问题#

C# 这个C语言中的反正弦近似的实现有什么问题#,c#,algorithm,math,trigonometry,C#,Algorithm,Math,Trigonometry,这是一个使用泰勒级数近似反正弦(x)的公式 这是我在C#中的实现,我不知道哪里是错误的位置,代码在运行时给出错误的结果: 当i=0时,除法为1/x。因此,我在启动时指定temp=1/x。对于每个迭代,我在“I”之后更改“temp”。 我使用连续循环,直到下一个值非常接近。当下一个数字的增量非常小时,我将返回该值 我的测试用例: 输入为x=1,因此超出的弧芯(x)将为弧芯(1)=PI/2=1.57079633 rad class Arc{ static double ab

这是一个使用泰勒级数近似反正弦(x)的公式

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

我的测试用例: 输入为x=1,因此超出的弧芯(x)将为弧芯(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();
            }
        }   
类弧{
静态双abs(双x)
{
返回x>=0?x:-x;
}
静态双功率(双亩,长n)
{
双kq=mu;

(长i=2;i注:我之所以将此作为社区维基答案,是因为我不是第一个想到这一点的人(只是第一个将其写在评论中)。如果您觉得需要添加更多内容才能使答案完整,请在中编辑它

一般的怀疑是,这是因为,您的一个值(可能是
fact()
iFactSquare()
的返回值)对于您选择的类型来说太大了。它会变为负数,因为您使用的是有符号类型-当它变为太大的正数时,它会循环回负数


尝试跟踪计算过程中
n
的大小,并计算出如果通过
fact
pow
iFactSquare
函数运行该数字,它会给你带来多大的数字。如果它比我们想象的大(假设你使用64位,32位的话,它会小得多),然后尝试使用。

注意:我将此作为一个社区wiki答案,因为我不是第一个想到这一点的人(只是第一个将其写在评论中)。如果您觉得需要添加更多内容才能使答案完整,请在中编辑它

一般的怀疑是,这是因为,您的一个值(可能是
fact()
iFactSquare()
的返回值)对于您选择的类型来说太大了。它会变为负数,因为您使用的是有符号类型-当它变为太大的正数时,它会循环回负数


尝试跟踪计算过程中
n
的大小,并计算出如果通过
fact
pow
iFactSquare
函数运行该数字,它会给你带来多大的数字。如果它比我们想象的大(假设你使用64位,32位的话,它会小得多),然后尝试使用。

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

                (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)的收敛性是有保证的,使用术语之间的商来更新术语通常是很方便的

                (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)保存两个不同的temp值(temp和tempNew)以检查继续计算是否无关时,才能保证收敛。这很好,但不保存这两个值的总和


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

e保存两个不同的临时值(temp和tempNew)以检查继续计算是否无关。这很好,只是您没有保存这两个值的总和


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

因此,我nput您给出了什么,结果是什么,您期望得到什么?请注意,
fact(2*i)
将很快溢出…第一个可疑的地方是
fact
,它被声明为
long
(这就是整数溢出很可能的原因);make
fact
返回
double
我的输入是x=1,因此超出的arcin(x)将是arcin(1)=PI/2=1.57079633 rad,但返回-1.203949002882805E-11@DmitryBychenko,temp是使用每个索引计算的,temp与前一个temp不相关。今天将是学习如何使用调试器的好日子。逐行检查代码的每一行,并在变量每次更改时进行观察。在每个变量更改之前,进行心理测试预测新值将是什么。最终你的预测将是错误的。要么代码是错误的,要么你的心智模型是错误的;无论哪种方式,你都发现了一个需要解决的问题。那么你给出了什么输入,结果是什么,你期望什么?请注意
fact(2*i)
将很快溢出…第一个可疑的位置是
事实
,它被声明为
(这就是为什么整数溢出是很有可能的);使
事实
返回
双精度
我的输入是x=1,所以超出的arcin(x)将是arcin(1)=PI/2=1.57079633 rad,但返回-1.203949002882805E-11@DmitryBychenko,temp是使用每个索引计算的,temp与前一个temp不相关。今天将是学习如何使用调试器的好日子。逐行检查代码的每一行,并在每次变量更改时进行观察