好的,所以Sin函数接受半径,并返回该半径的正弦值。
我听说几乎任何功能都可以用查找表替换。
无论我如何使用sin函数,我如何使用自己的查找表代替sin?
让我们举一个简单的例子found here.
/* sin example */
#include <stdio.h> /* printf */
#include <math.h> /* sin */
int main ()
{
double param, result;
param = 0.53;
result = sin (param);
printf ("The sine of %f is %f.\n", param, result );
return 0;
}
假设我想用我自己的256个浮点查找表替换sin函数。
#define TableSize 256.f
float SinArray[TableSize];
for(int i = 0; i < TableSize; i++)
{
// sin
SinArray[i] = static_cast<float>(sin( (i/TableSize)*(2.f*m_pi) ));
}
我现在如何使用此表替代使用sin函数。
您可能会问“为什么?为什么不使用sin函数?”好吧,因为我正在使用sin函数来波形输入音频。如果我可以使用查找表,我可以创建锯齿形或三角形
由于sin函数采用半径并返回该半径的正弦值,如何使用查找表复制此操作?我怎么做呢?
答案 0 :(得分:1)
您需要在表格中的两个值之间进行插值
伪代码:
float sin(float radius) {
radius = radius modulo 2*m_pi;
int idx = floor(TableSize * radius/2*m_pi);
float r = TableSize * radius/2*m_pi - idx;
return SinArray[idx] * (1-r) + SinArray[idx+1] * r;
}
答案 1 :(得分:0)
定期将半径映射到他们的罪恶值,这是你的表。当你想要使用它时,你想要一个值到表中最近的键的半径,那就是你的罪恶值。
或者绕半径,你想要一个值为最接近的整数并索引到一个数组。
答案 2 :(得分:0)
无法理解为什么要在普通/现代机器上执行此操作 - sin()
是硬件说明。
但是,为了好玩,你可以这样做:
const double tau = 2 * M_PI;
class Sin
{
public:
Sin(int tableSize = 256)
: tableSize_(tableSize)
{
initSinTable();
}
double operator()(double radians) const
{
double mapped = mapDomain(radians);
int idx = (int)floor(tableSize_ * mapped / tau);
double lambda = tableSize_ * mapped / tau - idx;
double lower = sinArray[idx] ;
double upper = 0;
if (idx < tableSize_ - 1)
upper = sinArray[idx + 1];
double res = lower * (1 - lambda) + upper *lambda;
return res;
}
private:
static double mapDomain(double d)
{
double mapped = fmod(d, tau);
if (mapped < 0)
mapped += tau;
return mapped;
}
int tableSize_;
std::vector<double> sinArray;
void initSinTable()
{
sinArray.resize(tableSize_);
for (int i = 0; i < tableSize_; ++i)
{
sinArray[i] = sin((i*1.0 / tableSize_)*tau);
}
}
};
int main()
{
Sin mySin(512);
std::cout << mySin(tau / 6) << std::endl;
std::cout << sin(tau / 6) << std::endl;
}
关于tau
的使用,请参阅:Wikipedia
答案 3 :(得分:0)
这是另一个实现,通用可重用于任意函数:
#include <iostream>
#include <vector>
#include <cmath>
#define LOG(X) (std::cout << X << '\n')
template <typename Num>
class Lookup
{
public:
Lookup(Num (*func)(Num), Num from, Num to, size_t num_samples)
: from_(from), to_(to), x_(double(num_samples - 1) / (to - from))
{
for (size_t i = 0; i < num_samples; ++i)
{
Num num = (to - from) * i / (num_samples - 1);
Num sample = func(num);
LOG("[" << i << "] f(" << num << ") == " << sample);
samples_.push_back(sample);
}
}
Num operator()(Num n) const
{
size_t index = round((n - from_) * x_);
LOG("(" << n << ") ~@ [" << (n - from_) << " / " << (to_ - from_)
<< " * " << (samples_.size() - 1) << "] == [" << index << "] == "
<< samples_.at(index) << "]");
return samples_.at(index);
}
private:
static Num round(Num n) { return std::floor(n + 0.5); }
std::vector<Num> samples_;
Num from_, to_, x_;
};
int main()
{
Lookup<double> lsin(std::sin, 0.0, 1.0, 21);
for (double d = 0; d <= 1.0; d += 0.1)
std::cout << d << ' ' << sin(d) << ' ' << lsin(d) << '\n';
}
它适用于float
或double
类型 - 可能不会使用floor
以及过早截断为整数的除法之外的任何其他内容有问题。
&#34;神秘地&#34;已预先计算名为x_
以加快operator()(Num)
;它可以被计算为除以的数量,但乘法有时在时钟周期方面更快。
记录只是表明它按预期工作:
[0] f(0) == 0
[1] f(0.05) == 0.0499792
[2] f(0.1) == 0.0998334
[3] f(0.15) == 0.149438
[4] f(0.2) == 0.198669
[5] f(0.25) == 0.247404
[6] f(0.3) == 0.29552
[7] f(0.35) == 0.342898
[8] f(0.4) == 0.389418
[9] f(0.45) == 0.434966
[10] f(0.5) == 0.479426
[11] f(0.55) == 0.522687
[12] f(0.6) == 0.564642
[13] f(0.65) == 0.605186
[14] f(0.7) == 0.644218
[15] f(0.75) == 0.681639
[16] f(0.8) == 0.717356
[17] f(0.85) == 0.75128
[18] f(0.9) == 0.783327
[19] f(0.95) == 0.813416
[20] f(1) == 0.841471
(0) ~@ [0 / 1 * 20] == [0] == 0]
0 0 0
(0.1) ~@ [0.1 / 1 * 20] == [2] == 0.0998334]
0.1 0.0998334 0.0998334
(0.2) ~@ [0.2 / 1 * 20] == [4] == 0.198669]
0.2 0.198669 0.198669
(0.3) ~@ [0.3 / 1 * 20] == [6] == 0.29552]
0.3 0.29552 0.29552
(0.4) ~@ [0.4 / 1 * 20] == [8] == 0.389418]
0.4 0.389418 0.389418
(0.5) ~@ [0.5 / 1 * 20] == [10] == 0.479426]
0.5 0.479426 0.479426
(0.6) ~@ [0.6 / 1 * 20] == [12] == 0.564642]
0.6 0.564642 0.564642
(0.7) ~@ [0.7 / 1 * 20] == [14] == 0.644218]
0.7 0.644218 0.644218
(0.8) ~@ [0.8 / 1 * 20] == [16] == 0.717356]
0.8 0.717356 0.717356
(0.9) ~@ [0.9 / 1 * 20] == [18] == 0.783327]
0.9 0.783327 0.783327
(1) ~@ [1 / 1 * 20] == [20] == 0.841471]
1 0.841471 0.841471