ゆるゆるプログラミング

・ニュートン法で平方根 その3

ニュートン法は、関数f(x)が与えられたときf(x)=0となるxを数値計算の反復によって求めるアルゴリズムの1つです。その計算式は以下です。

ニュートン法 漸化式

ここでは、ニュートン法を使って平方根を計算するメソッドの作り方を紹介します。

ニュートン法は、反復計算でf(x)=0のxの解を見つけていく方法ですが、解が見つからない場合に計算が収束せずに処理が終了できないことがあります。

メソッドの中でニュートン法を使い計算値を得ようとする場合は、解が得られない場合でも、処理を終了させて何かしらの値を戻す必要があります。このあたりのことをニュートン法平方根を計算するメソッドのソースコードで詳しく説明します。

関数をf(x)=x2-aとし、f(x)=0となるxを求めることで、aの平方根を計算します。

この式は、以下の手順で導いています。

ニュートン法 平方根を求める元の式

以下がそのJavaソースコードです。

NewtonsMethod.java ← クリックしてダウンロードページに移動
001:    public class NewtonsMethod {
002:    	// f(x)=x^2-a
003:    	static double f( double x, double a )
004:    	{
005:    		return x * x - a;
006:    	}
007:    
008:    
009:    	// f(x)の微分f'(x) - 接線の傾き
010:    	static double df( double x )
011:    	{
012:    		return 2 * x;
013:    	}
014:    
015:    
016:    	// ニュートン法 漸化式
017:    	static double newtons( double x, double a )
018:    	{
019:    		return x - f( x, a ) / df( x );
020:    	}
021:    
022:    
023:    	// ニュートン法で平方根を計算するメソッド
024:    	static double sqrt( double a )
025:    	{
026:    		// 変数の宣言
027:    		double e = 0.000001;	// 収束の判定値
028:    		double x;		// 計算値を格納
029:    		double x_ans;		// 1つ前の計算値
030:    
031:    		// aが0.0以下の場合、そのままのaの値を戻す
032:    		if ( 0.0 >= a ) return a;
033:    
034:    		// 初期値を代入
035:    		x_ans = 10000.0;
036:    
037:    		// 5000回のループ
038:    		for ( int i = 1; i <= 5000; ++ i ) {
039:    			// ニュートン法で計算
040:    			x = newtons( x_ans, a );
041:    
042:    			// 収束の判定
043:    			if ( e > Math.abs( x - x_ans ) )
044:    				return Math.abs( x );
045:    
046:    			// 最新の計算結果を次の計算結果に代入
047:    			x_ans = x;
048:    		}
049:    
050:    		// 収束しなかった場合、マイナスの値を戻す
051:    		return -1.0;
052:    	}
053:    
054:    
055:    	// メイン
056:    	public static void main(String[] args) {
057:    		// 変数の宣言
058:    		double a;
059:    
060:    		// 平方根を求める値を代入
061:    		a = 77.7 * 77.7;
062:    
063:    		// 結果の表示
064:    		System.out.println( a + "の平方根: " + sqrt( a ) );
065:    	}
066:    }

NewtonsMethodを実行

C:\talavax\javasample>java NewtonsMethod

6037.29(77.7×77.7)の平方根ニュートン法で計算してます。

NewtonsMethod.javaの出力結果

6037.290000000001の平方根: 77.7

平方根の計算結果が77.7になっています。

ここからは、Javaソースコードを順番に説明していきます。

001:    public class NewtonsMethod {

クラス名を、NewtonsMethodとしています。

002:    	// f(x)=x^2-a
003:    	static double f( double x, double a )
004:    	{
005:    		return x * x - a;
006:    	}

ニュートン法でf(x)=0を求めたい関数です。ここでは、f(x)=x2-aという関数を記述しています。平方根の元の値をaに代入します。

009:    	// f(x)の微分f'(x) - 接線の傾き
010:    	static double df( double x )
011:    	{
012:    		return 2 * x;
013:    	}

f(x)の微分式f'(x)を計算するメソッドです。

016:    	// ニュートン法 漸化式
017:    	static double newtons( double x, double a )
018:    	{
019:    		return x - f( x, a ) / df( x );
020:    	}

ニュートン法の漸化式のメソッドです。

023:    	// ニュートン法で平方根を計算するメソッド
024:    	static double sqrt( double a )
025:    	{

ニュートン法平方根を計算するメソッドです。double sqrt( double a)のdouble型の引数aに平方根を求める値を渡せば、結果がdouble型で戻ってきます。

026:    		// 変数の宣言
027:    		double e = 0.000001;	// 収束の判定値
028:    		double x;		// 計算値を格納
029:    		double x_ans;		// 1つ前の計算値

このプログラムで使う変数を宣言しています。double型変数eは、漸化式を終了させるための値で、計算したxn+1とxn絶対値の差がe未満になったときに計算を終了させます。

031:    		// aが0.0以下の場合、そのままのaの値を戻す
032:    		if ( 0.0 >= a ) return a;

引数で渡された値aが0.0以下の場合、aの値をそのままメソッドの戻り値にしています。a=0.0の平方根は0.0なので計算の必要がありません。また、aが0.0未満の場合には、平方根の計算ができないためaの値をそのまま戻しています。これにより、このメソッドでは戻り値が0.0未満のときに計算エラーと判断できるようにしています。

034:    		// 初期値を代入
035:    		x_ans = 10000.0;

計算の初期値に10000.0を代入しています。この値は任意です。、

037:    		// 5000回のループ
038:    		for ( int i = 1; i <= 5000; ++ i ) {

for文で5000回のループを作っています。これは5000回の計算を行った結果、計算値が収束しなかったら処理を強制終了させるものです。ループを5000回にしていることについては深い意味はありません。計算する関数f(x)によって変える必要があります。

これにより、計算結果が得られない場合でもメソッドから何かの値を返すようにしています。このメソッドの場合、for文を抜けると-1.0を返すようにしています。

039:    			// ニュートン法で計算
040:    			x = newtons( x_ans, a );

ニュートン法の漸化式にx_ansとaを渡して、次のxの値を取得しています。

042:    			// 収束の判定
043:    			if ( e > Math.abs( x - x_ans ) )
044:    				return Math.abs( x );

計算した値xと、計算に使った値x_ansの差の絶対値を計算し、その値がeより小さければ計算が収束したと判断し、return文でxの絶対値を戻します。これで計算終了です。

戻す値xに絶対値をとっているのは、ニュートン法の結果がプラス/マイナスのどちらの値になるかが不明のため絶対値をとっています。どちらの値をとるかは、関数f(x)と計算の初期値によって決まります。

046:    			// 最新の計算結果を次の計算結果に代入
047:    			x_ans = x;

x_ansにxを代入しています。この後、計算は続きます。

050:    		// 収束しなかった場合、マイナスの値を戻す
051:    		return -1.0;

計算が収束せずに、for文を抜けた場合に、この処理に到達します。return文で-1.0を返してメソッド終了です。

055:    	// メイン
056:    	public static void main(String[] args) {

このmainメソッドからプログラムを実行します。

060:    		// 平方根を求める値を代入
061:    		a = 77.7 * 77.7;

平方根を求める値をdouble型変数aに代入しています。a=77.7*77.7と記述しているので、変数aに=6037.29が代入されます。

063:    		// 結果の表示
064:    		System.out.println( a + "の平方根: " + sqrt( a ) );

平方根を求めるメソッドで計算したaの平方根の値をコンソールに出力しています。

■関連コンテンツ

ニュートン法 ニュートン法について
ニュートン法で平方根 ニュートン法で平方根を計算

■新着情報

2019.08.05 トランプの操作 トランプを操作するクラス
2019.07.29 整数の累乗 整数の累乗をメソッドを作ってみました

■広告

法人向けのETC専用カード

~約8,000名の受講生と80社以上の導入実績~ 企業向けプログラミング研修ならCodeCamp

日本最大級ショッピングサイト!お買い物なら楽天市場

 

 

 

 

 

 

 

 

 

Topへ