2017年03月03日(金) [長年日記]
■ [c][c++] exp10()
glibcにexp10という関数があることを知った。pow10もある。
exp10はCやC++の今の標準ライブラリには入っていない。いずれ入るのかな。
手元の環境(CentOS 7, GCC 4.8.5)だと、<cmath>をincludeすればC++でexp10を使えた。Cの場合は_GNU_SOURCEをdefineしてから<math.h>をincludeしないと警告が出る。
■ [c++] exp10()とstd::pow()とstd::exp()
10のべき乗を計算するプログラムでstd::powを使っていたのだけれど、結構遅い。代わりにexp10を使ったら少し速くなった。exp10を標準化して欲しい。
ところで、10^x は
10^x = (e^log(10))^x = e^(log(10) * x)
と変換できるので、std::expを使っても計算できる。試すと、これが一番速かった。xの範囲によって計算の速度が変わるのかもしれないけれど。以下に、xが0の近辺で10^xを計算するプログラムとその実行結果を示す。
#include <chrono>
#include <cmath>
#include <iomanip>
#include <iostream>
template<typename F>
void call(const std::string& name, F f) {
using namespace std::chrono;
constexpr int n = 10000000;
constexpr double d = 0.0001;
const auto s = system_clock::now();
double r = 1;
for (int i = -n; i <= n; ++i) {
r *= f(d * i / n);
}
const auto e = system_clock::now();
std::cout
<< std::setprecision(20)
<< r
<< ", " << duration_cast<milliseconds>(e - s).count() << " ms"
<< ", " << name
<< std::endl;
}
int main() {
call("std::pow", [](double x) {
return std::pow(10.0, x);
});
call("exp10", [](double x) {
return exp10(x);
});
call("std::exp", [](double x) {
constexpr double log_10 = std::log(10);
return std::exp(log_10 * x);
});
}
1.0389215324922376205, 2650 ms, std::pow 1.0389215324948466446, 2371 ms, exp10 1.0389215324923555261, 1832 ms, std::exp
[ツッコミを入れる]