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