log(自然対数)の計算

30分プログラム、その665。log(自然対数)の計算をしてみる。
logの近似式について -log(常用対数)の近似式を教えて戴きたいです。- 数学 | 教えて!gooというページを見付けました。ようするに、『ボクの環境だとlogがないんだけど、なんかいい近似式しらない?』ということです。
で、そこで紹介されている近似式が、なかなかいい精度を出していたのでPerlでコードを書いてみました。特に、引数が大きい値のとき、平方根をつかって1の近傍にもっていくあたりがすばらしい。

あ、あと、Perlでreduceを使うと「$aと$bを一回しか使ってないよ!」という警告がでてうざいので、部分的に警告を無効化にしてます。一回しか使わないことの何が悪いんだよー!

使い方

print ln(100),"\n"; # => 4.60517018598795

ちなみにGoogle電卓の答えは4.60517019でした。

ソースコード

#! /usr/bin/perl
# -*- mode:perl; coding:utf-8 -*-
#
# log.pl -
#
# Copyright(C) 2009 by mzp
# Author: MIZUNO Hiroki / mzpppp at gmail dot com
# http://howdyworld.org
#
# Timestamp: 2009/09/25 22:03:01
#
# This program is free software; you can redistribute it and/or
# modify it under MIT Lincence.
#

use strict;
use warnings;
use Data::Dumper;
use List::Util qw(reduce);

# 1の近傍で精度がよいlog
sub ln_near_one($){
    my ($x) = @_;
    my $y = ($x-1) / ($x+1);

    my $term = sub {
	my ($n) = @_;
	my $m = 2 * $n + 1;
	1 / $m * ($y ** $m)
    };
    {
	no warnings qw(once);
	2 * reduce { $a + $b } map { $term->($_) } 0 ... 10;
    }
}

sub ln($){
    my ($n) = @_;
    my $i=0;

    until(abs($n - 1) < 1){
	$n = sqrt $n;
	$i++;
    }

    (2**$i) * ln_near_one($n);
}

print ln_near_one(2),"\n";
print ln(100),"\n";