2019.05.23

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

はじめに

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

ニュートン法 漸化式

ここでは、数値微分を使ったニュートン法平方根を計算するプログラムを紹介します。

ニュートン法の式の中にf(x)をxで微分したf'(x)を含んでいますが、関数f(x)によってf'(x)を導くことが困難または不可能なことがあります。

そこで、微分の関数が分からなくてもf'(x)が計算できる数値微分を使い、ニュートン法の計算を行えるようにしました。

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

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

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

Javaソースコード

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

NewtonsMethod2.java

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
public class NewtonsMethod2 {
	// f(x)=x^2-a
	static double f( double x, double a )
	{
		return x * x - a;
	}


	// f(x)の微分f'(x) - 接線の傾き
	// 微分の式が分からない場合、微分の近似値を計算
	static double df_ex( double x, double a )
	{
		double h = 0.0000001;

		return ( f( x + h, a ) - f( x, a ) ) / h;
	}


	// ニュートン法 漸化式
	static double newtons( double x, double a )
	{
		return x - f( x, a ) / df_ex( x, a );
	}


	// メイン
	public static void main(String[] args) {
		// 変数の宣言
		double e = 0.000001;	// 収束の判定値
		double x;		// 計算値を格納
		double x_ans;		// 1つ前の計算値
		double a;		// 平行根を求める値

		// 平行根を求める値
		a = 169.0;	// 13×13

		// 初期値を代入
		x_ans = 10000.0;

		// 無限ループ
		for ( int i = 1; ; ++ i ) {
			// ニュートン法で計算
			x = newtons( x_ans, a );

			// 収束の判定
			if ( e > Math.abs( x - x_ans ) ) break;

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

			// 途中経過の表示
			System.out.println( "回数:" + i + "  計算結果: " + x_ans );
		}

		// 改行
		System.out.println();

		// 結果の表示
		System.out.println( "計算結果: " + x_ans );

		// 結果の絶対値
		x_ans = Math.abs( x_ans );
		System.out.println( a + "の絶対値: " + x_ans );

		// f(x)=0になるかを確認
		System.out.println( "f(" + x_ans + ")=" + f( x_ans, a ) );
	}
}

コンパイル ソースコードが「ANSI」の場合

C:\talavax\javasample>javac -encoding sjis NewtonsMethod2.java

コンパイル ソースコードが「UTF-8」の場合

C:\talavax\javasample>javac NewtonsMethod2.java

実行

C:\talavax\javasample>java NewtonsMethod2

169の平方根ニュートン法で計算してます。計算の途中経過と結果を表示しています。

出力結果

回数:1  計算結果: 5000.055835163439
回数:2  計算結果: 2500.0405926789967
回数:3  計算結果: 1250.05263083155
回数:4  計算結果: 625.0944750620009
回数:5  計算結果: 312.682233554483
回数:6  計算結果: 156.6113993198339
回数:7  計算結果: 78.84524510893075
回数:8  計算結果: 40.494340546011806
回数:9  計算結果: 22.333882320006264
回数:10  計算結果: 14.950430379777575
回数:11  計算結果: 13.127226391861301
回数:12  計算結果: 13.000616525291765
回数:13  計算結果: 13.000000014619735

計算結果: 13.000000014619735
169.0の絶対値: 13.000000014619735
f(13.000000014619735)=3.8011310721230984E-7

Javaソースコードの解説

001
public class NewtonsMethod2 {

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

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

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

009
010
011
012
013
014
015
016
	// f(x)の微分f'(x) - 接線の傾き
	// 微分の式が分からない場合、微分の近似値を計算
	static double df_ex( double x, double a )
	{
		double h = 0.0000001;

		return ( f( x + h, a ) - f( x, a ) ) / h;
	}

f(x)の微分式f'(x)を数値微分で行うメソッドです。xが0.0000001増加したときの、yの増加分を計算しています。f'(x)は(yの増加分/xの増加分)なので、その値をreturn文で戻しています。ここでは、xの増加分を0.0000001としていますが関数f(x)によって変更する必要があります。いろいろな値で試してください。

019
020
021
022
023
	// ニュートン法 漸化式
	static double newtons( double x, double a )
	{
		return x - f( x, a ) / df_ex( x, a );
	}

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

026
027
	// メイン
	public static void main(String[] args) {

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

028
029
030
031
032
		// 変数の宣言
		double e = 0.000001;	// 収束の判定値
		double x;		// 計算値を格納
		double x_ans;		// 1つ前の計算値
		double a;		// 平行根を求める値

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

034
035
		// 平行根を求める値
		a = 169.0;	// 13×13

平方根を求める値をdouble型変数aに代入しています。

ここでは169.0を変数aに代入しています。これにより、ニュートン法で収束させた値が169.0の平方根である13.0になることが期待できます。

037
038
		// 初期値を代入
		x_ans = 10000.0;

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

040
041
		// 無限ループ
		for ( int i = 1; ; ++ i ) {

for文無限ループを作っています。int型変数iを1からインクリメント(1を足す)しています、終了条件を記述していないので無限ループになります。

042
043
			// ニュートン法で計算
			x = newtons( x_ans, a );

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

045
046
			// 収束の判定
			if ( e > Math.abs( x - x_ans ) ) break;

計算した値xと、計算に使った値x_ansの差の絶対値を計算し、その値がeより小さければ計算が収束したと判断し、break文for文を抜けます。

048
049
			// 最新の計算結果を次の計算結果に代入
			x_ans = x;

x_ansにxを代入しています。

055
056
057
058
059
		// 改行
		System.out.println();

		// 結果の表示
		System.out.println( "計算結果: " + x_ans );

ニュートン法で求めた結果x_ansをコンソールに出力しています。

061
062
063
		// 結果の絶対値
		x_ans = Math.abs( x_ans );
		System.out.println( a + "の絶対値: " + x_ans );

計算結果x_ansの絶対値をとった値をコンソールに出力しています。これが、実際に求めたい平方根の値になります。このプログラムの場合、f(x)=x2-169.0を0.0にするxを求めるようにしてるため、xの値が13.0と-13.0の2つの値のどちらでもf(x)=0を満たすことが出来ます。これは初期値によりプラスとマイナスのどちらかの値をとります。例えば初期値を-10000.0にするとx_ans=-13になります。

065
066
		// f(x)=0になるかを確認
		System.out.println( "f(" + x_ans + ")=" + f( x_ans, a ) );

計算結果x_ansをメソッドfに代入して、その結果が0になっているか確認するための出力です。この例では、結果の表示が指数表記になっていて、数値の後に'E-7'が付いています。これは10の-7乗を意味しています。この結果から求めたx_ansでメソッドfが戻す値は0に近く、x_ansはaの平方根であることが確認できます。

以上です。

関連コンテンツ

反復によって数値計算を行うアルゴリズム、ニュートン法を解説しています。興味がある方は、記事をご覧ください。

2019.05.22

関数f(x)が与えられたときf(x)=0となるxを数値計算の反復によって求める方法を詳しく解説しています。

2019.05.22

反復計算の回数の上限があるニュートン法の解法ソースコードを紹介しています。

2019.05.24

処理を繰り返すために使用するfor文について解説しています。

2020.03.23

基本的な計算である足し算(加法)/引き算(減法)/掛け算(乗法)/割り算(除法)を行うプログラム作成。

2020.03.23

メソッドを抜けるときに使用するreturn文について説明しています。

2020.03.20

Javaのmainメソッドで受け取るパラメータについて解説しています。

2017.09.26

mainメソッドで受け取るパラメータの数の取得の仕方について解説しています。

2019.05.14

条件式を判断して処理を分岐する方法を詳しく説明しています。

2023.03.20

繰り返し処理(ループ)から強制的に抜けかたについて解説しています。

2017.07.14

変数やクラスに格納されている値をコンソール出力する方法は?

2020.03.23

プログラムの最初に実行されるメソッドは?

2022.12.13

プログラミングで使う変数って何?

2020.03.23

Javaのプログラムを書いてみませんか?プログラムの書き方をくわしく説明しています。

2020.03.23

「Javaソースコード」から実行可能な「オブジェクトコード」に変換する方法をくわしく説明しています。

2020.03.23

Javaのプログラムを作ってみませんか?プログラミングに必要なものの用意から実行までを説明しています。

2020.03.23

Javaの学習に役立つソースコードを多数紹介しています。是非、ご覧ください。

2022.09.10

Swingパッケージを使ってグラフィック表示を行う方法を解説しています。

2020.03.23

画像フォーマット形式・色・大きさ・傾きなどの変更、特定の図形(文字・記号など)を見つけたり、取り出したりする画像処理について詳しく解説。

2015.11.29

繰り返し処理を使ったJavaのソースコードサンプルを紹介しています。

2020.03.23

配列を使うJavaソースコードを多数紹介しています。

2021.05.18

数学に関係するJavaのメソッドやソースコードなどを紹介しています。

2022.10.25

三角形、台形、円などいろいろな図形の面積を計算するプログラムを紹介しています。詳しくは、記事をご覧ください。

2021.05.18

StringクラスとStringBuilderクラスを利用したプログラミングの仕方を紹介しています。

2016.12.16

Javaを使った簡単な応用プログラム(生年月日から年齢を計算プログラムなど)を紹介しています。

2022.07.07

プログラミング、ITに関する用語をまとめています。

2022.10.17

日本で使われてきた伝統文様「和柄」について解説しています。

2022.07.27

アルゴリズムって何?

2022.12.29

平方根の意味と、Math.sqrtメソッドの使い方をソースコードを使って詳しく解説しています。

2020.03.23

プログラミング言語とは?種類や特徴について説明しています。

2022.08.03

Javaプログラムの構成について解説しています。詳しくは、こちらをご覧ください。

2020.03.23

メソッドの定義方法を詳しく解説しています。Javaのサンプルソースコードを使った説明もあります。

2020.03.23

絶対値の意味と、Math.absメソッドの使い方をソースコードを使って詳しく解説しています。

2020.03.23

for文で変数名iがよく使われる理由について説明しています。興味のある方は是非。

2022.08.29

繰り返し処理の作り方を解説しています。

2016.03.02

整数型の変数に1を足すインクリメント、1つ引くデクリメントについて詳しく説明しています。

2020.03.23

コンピュータを制御するために使用する入力機能と出力機能を持つ装置のことをコンソールといいます。興味のある方は、ご覧ください。

2020.08.24

指数表記は、非常に大きな数値や、0に近い小さい数値を表現するときに使われる表記方法の1つです。興味のある方は、記事をご覧ください。

2020.03.23

「ゆるゆるプログラム」のコンテンツを紹介しています。興味のある方はこの記事をご覧ください。

2020.03.23

広告