0

まず、この自然対数の近似を使用しています。または、数式のより適切な表現については、こちら(4.1.27) を参照してください。

これが私の実装です:

constexpr double eps = 1e-12;

constexpr double my_exp(const double& power)
{
    double numerator = 1;
    ull denominator = 1;
    size_t count = 1;
    double term = numerator / denominator;
    double sum = 0;
    while (count < 20)
    {
        sum += term;
        numerator *= power;
        #ifdef _DEBUG
            if (denominator > std::numeric_limits<ull>::max() / count)
                throw std::overflow_error("Denominator has overflown at count " + std::to_string(count));
        #endif // _DEBUG
        denominator *= count++;
        term = numerator / denominator;
    }
    return sum;
}

constexpr double E = my_exp(1);

constexpr double my_log(const double& num)
{
    if (num < 1)
        return my_log(num * E) - 1;
    else if (num > E)
        return my_log(num / E) + 1;
    else
    {
        double s = 0;
        size_t tmp_odd = 1;
        double tmp = (num - 1) / (num + 1);
        double mul = tmp * tmp;
        while (tmp >= eps)
        {
            s += tmp;
            tmp_odd += 2;
            tmp *= mul / tmp_odd;
        }
        return 2 * s;
    }
}

これらの関数を実装したい理由がわかるでしょう。基本的には、 pow 関数を実装したいと考えています。しかし、それでも私のアプローチでは非常に不正確な回答が得られます。たとえば、my_log(10) = 2.30256 ですが、Google によると (ln 10 ~ 2.30259)

my_exp() は、テイラー展開が非常に収束しているため、非常に正確です。my_exp(1) = 2.718281828459、Google によると e^1 = 2.71828182846 です。しかし残念ながら、自然対数の場合は同じではなく、自然対数のこのシリーズがどのように導出されたのかさえわかりません(上記のリンクから意味します)。そして、このシリーズに関する情報源は見つかりませんでした。

精度の誤差はどこから来るのですか?

4

2 に答える 2