gpt4 book ai didi

C++ : sin(M_PI/6) = 0. 5?

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:31:40 25 4
gpt4 key购买 nike

我正在编写一个科学程序,它在其主要算法中使用正弦的公共(public)值,即 sin(M_PI/N)对于 N = 1, 2, 3, 4, 5, 6 .

因为我希望我的程序尽可能快,所以我想:让我们将这些值存储在一个 vector 中,而不是一遍又一遍地计算它们。它看起来像这样:

sin_pi_over_n_.clear();
sin_pi_over_n_.push_back(0.0);
sin_pi_over_n_.push_back(1.0);
sin_pi_over_n_.push_back(sqrt(3.0)/2.0);
sin_pi_over_n_.push_back(sqrt(2.0)/2.0);
sin_pi_over_n_.push_back(sqrt(2.0)*0.25*sqrt(5.0-sqrt(5.0)));
sin_pi_over_n_.push_back(0.5);

所以现在在我的主要算法中我写了s = sin_pi_over_n_[n-1];而不是 s = sin(M_PI/n); .

但令我大吃一惊的是,该程序竟然慢了几乎两倍!我想,真的,读取 vector 中的值需要那么长时间吗?但后来我意识到这不是问题:如果我改写

sin_pi_over_n_.push_back(sin(M_PI/1.0));
sin_pi_over_n_.push_back(sin(M_PI/2.0));
sin_pi_over_n_.push_back(sin(M_PI/3.0));
sin_pi_over_n_.push_back(sin(M_PI/4.0));
sin_pi_over_n_.push_back(sin(M_PI/5.0));
sin_pi_over_n_.push_back(sin(M_PI/6.0));

然后程序又快了!然后我想:我的正弦值有问题。但疯狂的是,即使我只替换最后一行 sin_pi_over_n_.push_back(sin(M_PI/6.0));通过 sin_pi_over_n_.push_back(0.5);然后程序又慢了!是关于 double 的吗?我有点怀疑:如果我问 std::cout << abs(sin(M_PI/6.0) - 0.5) << std::endl; , 我得到 0在我的终端。

糟糕:我才意识到;如果我问std::cout << sin(M_PI/6.0) - 0.5 << std::endl; (没有 abs ),然后我得到 -5.55112e-17 .我仍将继续并发布该问题,因为这种行为对我来说似乎不可思议。如果这种不可预知的现象对性能有如此大的影响,我怎么可能优化我的程序的速度?

感谢您的见解!

编辑:也许我还不够清楚。在我的程序中,我有一个类 Algo .当我执行我的程序时,一些功能,比如 my_function , 被称为无数次。在这个函数中,一行是:s = sin(M_PI/n); .我想我会用 s = sin_pi_over_n_[n-1]; 替换这一行, 其中sin_pi_over_n_[n-1]是一个 vector ,存储为类 Algo 的成员变量并且我一劳永逸地填入 Algo 的构造函数中.希望这能让事情变得更清楚。

编辑 2:好的,看来你们中的一些人希望我发布更多代码。来了:

Algo :

class Algo : public QThread
{
Q_OBJECT

public:
Algo() {}
void reset_algo(...)

public slots:
void run();

private:
void create_sines();
double super_total_neighbors_angle(const unsigned int &index, double &error);
double super_radius_update(const unsigned int &index, double &error);
// etc

std::vector<double> radii_;
std::vector<double> sin_pi_over_n_;
std::vector<unsigned int> neighbors_lists_sizes_;
// etc
};

成员函数create_sines :

void Algo::create_sines()
{
sin_pi_over_n_.clear();

/*sin_pi_over_n_.push_back(0.0);
sin_pi_over_n_.push_back(1.0);
sin_pi_over_n_.push_back(0.5*sqrt(3.0));
sin_pi_over_n_.push_back(0.5*sqrt(2.0));
sin_pi_over_n_.push_back(0.25*sqrt(2.0)*sqrt(5.0-sqrt(5.0)));
sin_pi_over_n_.push_back(0.5);*/

sin_pi_over_n_.push_back(sin(M_PI/1.0));
sin_pi_over_n_.push_back(sin(M_PI/2.0));
sin_pi_over_n_.push_back(sin(M_PI/3.0));
sin_pi_over_n_.push_back(sin(M_PI/4.0));
sin_pi_over_n_.push_back(sin(M_PI/5.0));
sin_pi_over_n_.push_back(sin(M_PI/6.0));

return;
}

成员函数super_radius_update (我在上面重命名为 my_function):

inline double Algo::super_radius_update(const unsigned int &index, double &error)
{
int n = neighbors_lists_sizes_[index];
double s = sin(super_total_neighbors_angle(index, error)*0.5/n);
double rv = radii_[index]*s/(1-s);
//s = sin(M_PI/n);
s = sin_pi_over_n_[n-1];
return (1-s)*rv/s;
}

恐怕我很难发送一个您可以运行的最小完整示例,因为整个类(class)有点长和复杂。我可以尝试,但我仍然必须发布大量代码,而且我需要相当长的时间来提取...

我在 Linux Ubuntu 12.04 64 位笔记本电脑上使用 Qt Creator 4.8 64 位。

编辑 3 或 4:对于所有的编辑,我深表歉意。有一个重要的信息我没有告诉你:程序将运行(基本上调用函数 super_radius_update)直到一些错误在一定的容忍范围内。因此,使程序变慢或变快的不是 super_radius_update 的执行时间。但我相信该函数的调用次数。对 sin(M_PI/N) 使用这样或那样的值将对错误达到容差的速度产生影响。

最佳答案

double rv = radii_[index]*s/(1-s);
return (1-s)*rv/s;

此代码在 s = 0s = 1 处有奇点,这两者都会发生,并且由于奇点而在数值上不稳定。您可能通过 sin_pi_over_n_[0]sin_pi_over_n_[1] 的不同计算触发了不稳定性。

虽然这不能解释不同 sin_pi_over_n_[5] 计算的不同行为,但可能存在类似的不稳定性。

关于C++ : sin(M_PI/6) = 0. 5?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11331932/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com