使用C计算maclaurin级数的正弦 [英] Calculate maclaurin series for sin using C

查看:51
本文介绍了使用C计算maclaurin级数的正弦的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个使用其maclaurin系列计算正弦的代码,它可以工作,但是当我尝试为较大的x值计算正弦并尝试通过给出大阶数N(总和的长度)来抵消它时-最终它会溢出并没有给我正确的结果.这是代码,我想知道是否还有其他方法可以对其进行优化,因此它也适用于较大的x值(对于较小的x值和非常大的N值,它已经非常有效).这是代码:

I wrote a code for calculating sin using its maclaurin series and it works but when I try to calculate it for large x values and try to offset it by giving a large order N (the length of the sum) - eventually it overflows and doesn't give me correct results. This is the code and I would like to know is there an additional way to optimize it so it works for large x values too (it already works great for small x values and really big N values). Here is the code:

long double calcMaclaurinPolynom(double x, int N){
    long double result = 0;
    long double atzeretCounter = 2;
    int sign = 1;
    long double fraction = x;

    for (int i = 0; i <= N; i++)
    {
        result += sign*fraction;
        sign = sign*(-1);
        fraction = fraction*((x*x) / ((atzeretCounter)*(atzeretCounter + 1)));
        atzeretCounter += 2;

    }
    return result;
}

推荐答案

主要问题是使用序列收敛范围之外的序列.

The major issue is using the series outside its range where it well converges.

由于OP表示将x转换为radX =(x * PI)/180",表明OP以度而不是弧度开始,所以运气很好.查找 my_sin(x)的第一步是范围缩小.从度数开始,减少是精确的.因此,请减小转换为弧度之前的范围.

As OP said "converted x to radX = (x*PI)/180" indicates the OP is starting with degrees rather than radians, the OP is in luck. The first step in finding my_sin(x) is range reduction. When starting with degrees, the reduction is exact. So reduce the range before converting to radians.

long double calcMaclaurinPolynom(double x /* degrees */, int N){
  // Reduce to range -360 to 360
  // This reduction is exact, no round-off error
  x = fmod(x, 360);  

  // Reduce to range -180 to 180
  if (x >= 180) {
    x -= 180;
    x = -x;
  } else if (x <= -180) {
    x += 180;
    x = -x; 
  }

  // Reduce to range -90 to 90
  if (x >= 90) {
    x = 180 - x;
  } else if (x <= -90) {
    x = -180 - x;
  }

  //now convert to radians.
  x = x*PI/180;
  // continue with regular code

或者,如果使用C11,则使用 remquo().在SO中搜索示例代码.

Alternative, if using C11, use remquo(). Search SO for sample code.

如@ user3386109上面所述,无需转换回学位".

As @user3386109 commented above, no need to "convert back to degrees".

使用典型的求和级数,对最低有效项 first 求和可以提高答案的准确性.使用OP的代码,可以使用

With typical summation series, summing the least significant terms first improves the precision of the answer. With OP's code this can be done with

for (int i = N; i >= 0; i--)

或者,循环而不是重复固定的次数,直到该项对总和没有意义为止.以下内容使用递归来对最不重要的术语进行求和.将范围缩小到-90至90范围内,迭代次数不会过多.

Alternatively, rather than iterating a fixed number of times, loop until the term has no significance to the sum. The following uses recursion to sum the least significant terms first. With range reduction in the -90 to 90 range, the number of iterations is not excessive.

static double sin_d_helper(double term, double xx, unsigned i) {
  if (1.0 + term == 1.0)
    return term;
  return term - sin_d_helper(term * xx / ((i + 1) * (i + 2)), xx, i + 2);
}


#include <math.h>
double sin_d(double x_degrees) {

  // range reduction and d --> r conversion from above
  double x_radians = ...

  return x_radians * sin_d_helper(1.0, x_radians * x_radians, 1);
}

这篇关于使用C计算maclaurin级数的正弦的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆