【问题标题】:sine wave generation in c++c++中的正弦波生成
【发布时间】:2018-10-26 05:29:12
【问题描述】:

我正在尝试生成一组点,这些点在绘制为图形时表示 1 个周期的正弦波。要求是:

  • 1 个周期的正弦波
  • 下限 = 29491
  • 上限 = 36043
  • 点数 = 100
  • 幅度 = 3276
  • 零偏移 = 32767

代码:

int main()
{
    ofstream outfile;
    outfile.open("data.dat",ios::trunc | ios::out);
    for(int i=0;i<100;i++)
    {
        outfile << int(3276*sin(i)+32767) << "\n";
    }
    outfile.close();
    return 0;
}

我正在生成点并将其存储在文件中。绘制这些点后,我得到以下图表。

但我只需要一个周期。我该怎么做?

【问题讨论】:

  • 什么是“下限”和“上限”?
  • 首先你必须记住std::sin 需要一个角度。而一个完整的周期是 360 度。而std::sin 希望它的角度以 弧度 为单位(即一个周期是 2π 度)。
  • 阅读 the docs: arg - value representing angle in radians - 不仅仅是“0 到 100,计算机会知道我的真正意思”
  • 你错过的请注明wavelength

标签: c++ trigonometry


【解决方案1】:

代入sine wave的公式:

y(t) = A * sin(2 * PI * f * t + shift)

地点:

A = 幅度,函数与零的峰值偏差。
f = 普通频率,振荡次数(周期)
t = 时间
shift = 相移

应该是:

y[t] = AMPLITUDE * sin (2 * M_PI * 0.15 * t + 0) + ZERO_OFFSET;
                                   ^^^ f = 15 cycles / NUM_POINTS = 0.15 Hz

要获得一个完整周期,从y[0:t) 循环,其中t 是完成一个完整周期(即波长)所需的时间或点数

【讨论】:

    【解决方案2】:

    看来您需要 100 个样本进行一个周期,所以您可能需要这个:

    ...
    #define _USE_MATH_DEFINES
    #include <math.h>
    ...
    #define NB_OF_SAMPLES 100
    ...
      double angle = 0.0;
      for (int i = 0; i < NB_OF_SAMPLES; i++)
      {
        outfile << int(3276 * sin(angle) + 32767) << "\n";
        angle += (2 * M_PI) / NB_OF_SAMPLES;
      }
    ...
    

    或者更好:

    #define NB_OF_SAMPLES 100
    #define OFFSET        3276
    #define AMPLITUDE     32767
    
    ...
      double angle = 0.0;
      for (int i = 0; i < NB_OF_SAMPLES; i++)
      {
        outfile << int(AMPLITUDE * sin(angle) + OFFSET) << "\n";
        angle += (2 * M_PI) / NB_OF_SAMPLES;
      }
    ...
    

    【讨论】:

      【解决方案3】:

      一个完整的循环由 360 度组成。所需样本为 100。
      所以步长是 3.6

      int main()
      {
          ofstream outfile;
          outfile.open("data.dat",ios::trunc | ios::out);
          for(int i=0;i<101;i++)
          {
              float rads = M_PI/180;
              outfile << (float)(3276*sin(3.6*i*rads)+32767) << endl;
          }
          outfile.close();
          return 0;
      }
      

      如果样本数为 200,则步长为 360/200 = 1.8

      int main()
      {
          ofstream outfile;
          outfile.open("data.dat",ios::trunc | ios::out);
          for(int i=0;i<201;i++)
          {
              float rads = M_PI/180;
              outfile << (float)(3276*sin(1.8*i*rads)+32767) << endl;
          }
          outfile.close();
          return 0;
      }
      

      输出:

      【讨论】:

        【解决方案4】:

        您需要更改 for 循环以从 0 迭代到 2(pi)。这是正弦波的一个周期。您可能还想将循环计数器更改为双精度而不是整数,并增加 0.1 或其他值。 screenshot from WolframAlpha.com

        【讨论】:

          【解决方案5】:

          数学正弦函数std::sin 以弧度表示其参数:

          arg - 以弧度表示角度的值,浮点数或 积分型

          如果您需要 1 个周期和 100 个点,那么知道一个周期中有 2pi 弧度,您需要类似

          double rads;
          for(int i=1;i<=100;i++)
          {
              rads = 2.0*M_PI*i/100;
              // your expression in terms of std::sin(rads)
          }
          

          如果您的编译器/库没有开箱即用的 M_PI,那么请查看 here 以获取应该使其可用的标志。

          还有一点没有涉及到您应该生成的确切间隔。如果您需要闭合区间 [0,2pi],则需要调整步长。我给出了一个半开区间 (0,2pi],@Michael Walz 给出了另一个半开区间 [0,2pi)。

          【讨论】:

          • /i 呃,没有。你的意思是* (i / 100.0)。我的意思是,你写的第一次迭代是即时 UB!
          • 请注意M_PI 不是标准宏,并非所有库都定义它。
          • @Some程序员老兄你有没有使用过一个不容易获得的编译器/库?
          • 我在某处看到它丢失了,但那是前一段时间了。但是,考虑到它包含在 MSVC 标头中并由 POSIX 强制执行,它几乎(但不完全)是通用的。
          猜你喜欢
          • 2012-07-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-02-21
          • 2015-02-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多