Skip to content

Instantly share code, notes, and snippets.

@xtetsuji
Created September 17, 2020 16:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xtetsuji/fe02c80bf8207f416e9438bfd105a0e8 to your computer and use it in GitHub Desktop.
Save xtetsuji/fe02c80bf8207f416e9438bfd105a0e8 to your computer and use it in GitHub Desktop.
Get square root by Newton's method.
#!/usr/bin/env perl
use v5.14;
use constant MAX_NEWTON_ITERATION_COUNT => 8;
print "平方根をニュートン法で求めます\n";
print "1より大きい自然数を入れて下さい: ";
my $input = <STDIN>;
chomp $input;
if ( !$input || $input <= 1 ) {
die "1より大きい自然数ではありませんでした\n";
}
my $sqrt_newton = sqrt_newton($input);
my $sqrt_core = sqrt($input);
print "平方根の近似値は $sqrt_newton です\n";
print "なお sqrt 組み込み関数の結果は $sqrt_core です\n";
print "小数点以下の桁数は"
. length($sqrt_newton =~ s/^\d+\.//r) . " 桁中 "
. match_max_decimal($sqrt_newton, $sqrt_core) . "桁あっています\n";
sub sqrt_newton {
my $number = shift;
my $func = get_func($number);
my $x = $number; # 初期値
$x = $func->($x) for 1..MAX_NEWTON_ITERATION_COUNT;
return $x;
}
sub get_func {
my $c = shift;
return sub {
my $x = shift;
return( 0.5 * ($x + $c / $x) );
};
}
sub match_max_decimal {
my ($n1, $n2) = @_;
s/^\d+\.// for $n1, $n2;
my $i = 0;
for my $pair (zipstr($n1, $n2)) {
my ($c1, $c2) = @$pair;
if ( $c1 ne $c2 ) {
return $i;
}
$i++;
}
return $i;
}
# List::MoreUtils::zip6( split(//, $str1), split(//, $str2) ) と大体同じ
sub zipstr {
my ($str1, $str2) = @_;
my @ar1 = split //, $str1;
my @ar2 = split //, $str2;
my $i = 0;
my @pairs;
while ( defined $ar1[$i] && defined $ar2[$i] ) {
push @pairs, [$ar1[$i], $ar2[$i]];
$i++;
}
return @pairs;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment