我正在尝试为Octave写一个.oct函数,给定一个正弦波值,介于-1和1之间,正弦波周期,返回一个周期长度的正弦波矢量,矢量中的最后一个值是给定的正弦波值。到目前为止我的代码是:
#include <octave/oct.h>
#include <octave/dColVector.h>
#include <math.h>
#define PI 3.14159265
DEFUN_DLD (sinewave_recreate, args, , "args(0) sinewave value, args(1) is period")
{
octave_value_list retval;
double sinewave_value = args(0).double_value ();
double period = args(1).double_value ();
ColumnVector output_sinewave(period);
double degrees_inc = 360 / period;
double output_sinewave_degrees;
output_sinewave_degrees = asin( sinewave_value ) * 180 / PI;
output_sinewave(period-1) = sin( output_sinewave_degrees * PI / 180 );
for (octave_idx_type ii (1); ii < period; ii++) // Start the loop
{
output_sinewave_degrees = output_sinewave_degrees - degrees_inc;
if ( output_sinewave_degrees < 0 )
{
output_sinewave_degrees += 360 ;
}
output_sinewave( period-1-ii ) = sin( output_sinewave_degrees * PI / 180 );
}
retval(0) = output_sinewave;
return retval;
}
但是给出了不完整的结果。通过这种方式,我的意思是它有时会非常精确地重现正弦波,有时则会有所不同。我只是通过创建给定的正弦波来确定这一点,将最后一个值及时插入到函数中,以便通过时间向后重新创建正弦波,然后比较两者的曲线。显然我做错了什么,但我似乎无法确定是什么。
答案 0 :(得分:4)
让我们从一些三角形身份开始:
sin(x)^2 + cos(x)^2 == 1
sin(x+y) == sin(x)*cos(y) + sin(y)*cos(x)
cos(x+y) == cos(x)*cos(y) - sin(x)*sin(y)
给定x
点处的正弦和余弦,我们可以在预算d
和sd = sin(d)
之后精确计算尺寸为cd = cos(d)
的步长后的值:
sin(x+d) = sin(x)*cd + cos(x)*sd
cos(x+d) = cos(x)*cd - sin(x)*sd
给定初始正弦值,您可以计算初始余弦值:
cos(x) = sqrt(1 - sin(x)^2)
请注意,有两种可能的解决方案,对应于两个可能的平方根值。另请注意,这些身份中的所有角度都是以弧度为单位,如果您回过波浪,则d
需要为负。
答案 1 :(得分:1)
#include <octave/oct.h>
#include <octave/dColVector.h>
#include <math.h>
#define PI 3.14159265
DEFUN_DLD (sinewave_recreate_3, args, , "args(0) sinewave value, args(1) is period, args(2) is the phase")
{
octave_value_list retval;
double sinewave_value = args(0).double_value ();
double period = args(1).double_value ();
double phase = args(2).double_value ();
ColumnVector output_sinewave(period);
double X0 = asin(sinewave_value);
if (sinewave_value < 0 & phase > 180 & phase < 270)
{
X0 = PI + (0 - X0);
}
if (sinewave_value < 0 & phase >= 270)
{
X0 = X0 + 2 * PI;
}
if (sinewave_value > 0 & phase > 90)
{
X0 = PI - X0;
}
if (sinewave_value > 0 & phase < 0)
{
X0 = X0 + PI / 2;
}
double dx = PI / 180 * (360/period);
for (octave_idx_type ii (0); ii < period; ii++) // Start the loop
{
output_sinewave(period-1-ii) = sin(X0 - dx * ii);
}
retval(0) = output_sinewave;
return retval;
}
谢谢Keynslug。
答案 2 :(得分:1)
有简单的公式。以下是Python中的示例:
import math
import numpy as np
# We are supposing step is equal to 1degree
T = math.radians(1.0/360.0)
PrevBeforePrevValue = np.sin(math.radians(49.0)) # y(t-2)
PrevValue = np.sin(math.radians(50.0)) # y(t-1)
ValueNowRecursiveFormula = ((2.0*(4.0-T*T))/(4.0+T*T))*PrevValue - PrevBeforePrevValue
print("From RECURSIVE formula - " + str(ValueNowRecursiveFormula))
详情可在此处找到: http://howtodoit.com.ua/en/on-the-way-of-developing-recursive-sinewave-generator/
答案 3 :(得分:0)
您可以尝试一种更简单的方法。 回想一下,如果
y = sin(x)
然后y
的一阶导数将等于
dy/dx = cos(x)
因此,在计算的每个步骤中,您都会将y
的当前值添加到等于
dy = cos(x) * dx
但这可能会降低你的准确性作为副作用。你可以探究它。 HTH。
似乎稍微改进的等式往往更准确:
dy = cos(x + dx/2) * dx
看看this。