2

生成任意长度的有符号浮点数组的最有效方法是什么,该数组包含 C 中正弦波的幅度(表示为从 1 到 -1)?

4

3 回答 3

3

正如 Carl Smotricz 在他的回答中指出的那样,您可以轻松编写一个简单的 C 程序来为您构建一个硬编码的数组。

以下代码可以解决问题:

int main(int argc, char * argv[])
{
    const int tableSize = 10;
    const char * fileName = "sin_table.txt";

    int x;
    FILE * file;

    file = fopen(fileName, "w");
    if (file == NULL) { printf("unable to open file\n"); return -1; }

    fprintf(file, "float sin_table[%d] =\n{\n ", tableSize);
    for (x = 0; x < tableSize; x++)
    {
        fprintf(file, "\t%f,\n", sinf(x*2*pi/tableSize));
    }
    fprintf(file, "};\n");

    fclose(file);
    return 0;
}

输出如下所示:

float sin_table[10] =
{
    0.000000,
    0.587785,
    0.951057,
    0.951056,
    0.587785,
    -0.000000,
    -0.587785,
    -0.951057,
    -0.951056,
    -0.587785,
};
于 2009-12-19T04:37:14.430 回答
3

如果您想要非常快的东西,请使用表格(如前所述)。

另一种方法是模拟一个小正弦振荡器并使用它来生成您的数据阵列。

这是一个如何执行此操作的示例:

int main (int argc, char **args)
{
  int i;

  float data[1024];
  float angle = 2.0f * 3.14 / 1024;

  // start of the sine-wave:
  float sinval = 0;
  float cosval = 1;

  // rotation per iteration
  float delta_sin = sinf(angle);
  float delta_cos = cosf(angle);

  for (i=0; i<1024; i++)
  {
    // store current value:
    data[i] = sinval;

    // update the oscillator:
    float s = sinval * delta_cos - cosval * delta_sin;
    float c = sinval * delta_sin + cosval * delta_cos;
    sinval = s;
    cosval = c;
  }
}

这背后的技巧是,我们从二维空间中的一个固定点开始,存储在 9sinval, cosval) 中。此外,我预先计算了(delta_cos,delta_sin)中单次旋转的参数。

我在循环中所做的就是用固定旋转将点旋转 1024 次。这会在每次迭代中创建一个 sin/cos 对。(注意:它与复数乘法相同)。

这种方法迟早会变得不稳定,不如在循环中调用 sin/cos 精确。

所以用它创建大表不是一个好主意,但如果你能忍受一个轻微的错误和多达一万个元素的小表,它是非常有用的。要解决该问题,您可以将类型更改为双精度,进行适当的舍入或每 n 次迭代重新规范化结果。


编辑:刚刚用双重和 1e9 迭代测试了代码。为我工作。我的相位略有漂移,但结果仍然比使用单精度 sinf/cosf 更准确。

于 2009-12-19T04:44:11.673 回答
2

如果您不希望运行时开销,请为自己编写一个小程序,将您的所有值打印为 C 数组声明/初始化,然后#include将该文件打印到您的程序中。

于 2009-12-19T04:22:53.010 回答