1

我正在尝试为 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;                                                                        
}

但给出了不完整的结果。我的意思是它有时会非常准确地重新创建正弦波,而其他时候则很遥远。我通过创建一个给定的正弦波来确定这一点,及时获取最后一个值并将其插入函数中以通过时间向后重新创建正弦波,然后比较两者的图。显然我做错了什么,但我似乎无法确定是什么。

4

4 回答 4

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,精确计算出一个大小的值:dsd = 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如果您要通过波返回,则需要为负。

于 2010-10-19T12:06:02.073 回答
1

Mike 注意到 cos(x) 有两种可能的解决方案让我意识到我需要解决正弦波的相位模糊问题。我对该功能的第二次成功尝试是:

#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。

于 2010-10-20T01:09:16.047 回答
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/

于 2015-04-13T08:16:39.807 回答
0

你可以尝试一种更简单的方法来通过。回想一下,如果

y = sin(x)

那么一阶导数y将等于

dy/dx = cos(x)

因此,在计算的每一步中,您都会添加y一些 delta 的当前值等于

dy = cos(x) * dx

但这可能会降低您的准确性作为副作用。你可以随便试探。HTH。


似乎稍微改进的方程往往更准确:

dy = cos(x + dx/2) * dx

看看这个

于 2010-10-19T06:47:39.397 回答