在C++中生成正弦波

5
我将尝试生成一组点,当作图时可呈现一个周期为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;
}

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

enter image description here

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


1
什么是“下限”和“上限”? - Holt
4
首先,您需要记住std::sin接受的是一个“角度”,完整的一圈是360度。而std::sin要求其角度以“弧度”表示(即一圈为2π度)。 - Some programmer dude
2
阅读文档: arg - 表示弧度角的值 - 不要仅仅使用 '0到100,计算机就知道我想要什么'。 - underscore_d
你忘记指定“波长”了。 - Joseph D.
5个回答

10

考虑到正弦波的公式:

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

where:

A = the amplitude, the peak deviation of the function from zero.
f = the ordinary frequency, the number of oscillations (cycles)
t = time
shift = phase 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是完成一个完整周期(即波长)所需的时间或点数。

3
看起来您需要一个周期需要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;
  }
...

1
一个完整的周期包含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;
}

输出:

enter image description here


0

数学正弦函数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,那么可以查看这里的标志来使其可用。

还有一件事情没有提到,那就是你应该生成的确切区间。如果你需要闭区间[0,2pi],那么你需要调整步长。我给出了一个半开区间(0,2pi],@Michael Walz给出了另一个半开区间[0,2pi)。


1
/ i 的意思是除以 i,不是乘以 i。我的意思是,你所写的第一次迭代是即时 UB! - underscore_d
2
请注意,M_PI不是标准宏,不是所有库都定义了它。 - Some programmer dude
1
@Some programmer dude 你有没有使用过一个没有易于获取的编译器/库? - Paul Floyd
我曾经看到过它在某个地方丢失了,但那是一段时间之前的事了。然而,考虑到它包含在MSVC头文件中并被POSIX强制要求,它几乎是(但不完全是)普遍存在的。 - Some programmer dude

0

你需要将for循环更改为从0到2(pi)进行迭代。这是正弦波的一个周期。你可能还想将循环计数器更改为double而不是整数,并以0.1或其他值递增。

来自WolframAlpha.com的截图

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接