情報学部 菅沼ホーム 目次 索引

非線形方程式(セカント法)

    1. A. C++
    2. B. Java
    3. C. JavaScript
    4. D. PHP
    5. E. Ruby
    6. F. Python
    7. G. C#
    8. H. VB

  プログラムは,f(x) = exp(x) - 3x = 0 の根をセカント法で求めた例です.

  1. C++

    /*************************************/
    /* セカント法による exp(x)-3x=0 の根 */
    /*      coded by Y.Suganuma          */
    /*************************************/
    #include 
    #include 
    
    double secant(double, double, int, double, double, int *,
                  double(*)(double));
    double snx(double);
    
    int main()
    {
    	double eps1, eps2, x, x1, x2;
    	int max, ind;
    /*
              データの設定
    */
    	eps1 = 1.0e-10;
    	eps2 = 1.0e-10;
    	max  = 100;
    	x1   = 0.0;
    	x2   = 1.0;
    /*
              実行と結果
    */
    	x = secant(x1, x2, max, eps1, eps2, &ind, snx);
    
    	printf("   ind=%d  x=%f  f= %f\n", ind, x, snx(x));
    
    	return 0;
    }
    
    /****************/
    /* 関数値の計算 */
    /****************/
    double snx(double x)
    {
    	double y;
    	y = exp(x) - 3.0 * x;
    	return y;
    }
    
    /*********************************************************/
    /* secant法(はさみうち法)による非線形方程式f(x)=0の解  */
    /*      x1,x2 : 初期値(x1 < x2)                        */
    /*      max : 最大試行回数                               */
    /*      eps1 : 終了条件1(|x(k+1)-x(k)|<eps1)       */
    /*      eps2 : 終了条件2(|f(x(k))|<eps2)           */
    /*      ind : > 0 : 収束回数                             */
    /*            =-1 : 収束しなかった                       */
    /*      g : f(x)を計算する関数名                         */
    /*      return : 解                                      */
    /*********************************************************/
    #include 
    
    double secant(double x1, double x2, int max, double eps1, double eps2,
                  int *ind, double (*g)(double))
    {
    	double f, f1, f2, x = 0.0;
    	int count;
    
    	count = 0;
    	*ind  = 0;
    	f1    = (*g)(x1);
    	f2    = (*g)(x2);
    
    	if (fabs(f1) < eps2)
    		x = x1;
    	else {
    		if (fabs(f2) < eps2)
    			x = x2;
    		else {
    			while (*ind == 0) {
    				count += 1;
    				if (fabs(f2-f1) < eps2)
    					*ind = -1;
    				else {
    					x = x2 - f2 * (x2 - x1) / (f2 - f1);
    					f = (*g)(x);
    					if (fabs(f) < eps2 ||
    						 fabs(x2-x1) < eps1 || fabs(x2-x1) < eps1*fabs(x2))
    						*ind = count;
    					else {
    						if (count < max) {
    							if (f1*f2 < 0.0) {
    								x2 = x;
    								f2 = f;
    							}
    							else {
    								x1 = x;
    								f1 = f;
    							}
    						}
    						else
    							*ind = -1;
    					}
    				}
    			}
    		}
    	}
    
    	return x;
    }
    			

  2. Java

    /*************************************/
    /* セカント法による exp(x)-3x=0 の根 */
    /*      coded by Y.Suganuma          */
    /*************************************/
    import java.io.*;
    
    public class Test {
    	public static void main(String args[]) throws IOException
    	{
    		double eps1, eps2, x, x1, x2;
    		int max, ind[] = new int [1];
    	/*
    	          データの設定
    	*/
    		eps1 = 1.0e-10;
    		eps2 = 1.0e-10;
    		max  = 100;
    		x1   = 0.0;
    		x2   = 1.0;
    	/*
    	          実行と結果
    	*/
    		Kansu kn = new Kansu();
    		x = kn.secant(x1, x2, max, eps1, eps2, ind);
    
    		System.out.println("   ind=" + ind[0] + "  x=" + x + "  f=" + kn.snx(x));
    	}
    }
    
    /****************/
    /* 関数値の計算 */
    /****************/
    class Kansu extends Secant
    {
    	double snx(double x)
    	{
    		double y = Math.exp(x) - 3.0 * x;
    		return y;
    	}
    }
    
    abstract class Secant
    {
    	/*********************************************************/
    	/* secant法(はさみうち法)による非線形方程式f(x)=0の解  */
    	/*      x1,x2 : 初期値(x1 < x2)                        */
    	/*      max : 最大試行回数                               */
    	/*      eps1 : 終了条件1(|x(k+1)-x(k)|<eps1)       */
    	/*      eps2 : 終了条件2(|f(x(k))|<eps2)           */
    	/*      ind : > 0 : 収束回数                             */
    	/*            =-1 : 収束しなかった                       */
    	/*      return : 解                                      */
    	/*********************************************************/
    
    	abstract double snx(double x);   // 定義しておく必要あり
    
    	double secant(double x1, double x2, int max, double eps1, double eps2, int ind[])
    	{
    		double f, f1, f2, x = 0.0;
    		int count;
    
    		count  = 0;
    		ind[0] = 0;
    		f1     = snx(x1);
    		f2     = snx(x2);
    
    		if (Math.abs(f1) < eps2)
    			x = x1;
    		else {
    			if (Math.abs(f2) < eps2)
    				x = x2;
    			else {
    				while (ind[0] == 0) {
    					count += 1;
    					if (Math.abs(f2-f1) < eps2)
    						ind[0] = -1;
    					else {
    						x = x2 - f2 * (x2 - x1) / (f2 - f1);
    						f = snx(x);
    						if (Math.abs(f) < eps2 ||
    						    Math.abs(x2-x1) < eps1 || Math.abs(x2-x1) < eps1*Math.abs(x2))
    							ind[0] = count;
    						else {
    							if (count < max) {
    								if (f1*f2 < 0.0) {
    									x2 = x;
    									f2 = f;
    								}
    								else {
    									x1 = x;
    									f1 = f;
    								}
    							}
    							else
    								ind[0] = -1;
    						}
    					}
    				}
    			}
    		}
    
    		return x;
    	}
    }
    			

  3. JavaScript

      ここをクリックすると,JavaScript の仕様に適合した形で解を求めたい式を入力することによって,任意の非線形方程式の解を画面上で求めることができます.
    <!DOCTYPE HTML>
    
    <HTML>
    
    <HEAD>
    
    	<TITLE>非線形方程式(セカント法)</TITLE>
    	<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
    	<SCRIPT TYPE="text/javascript">
    		str = "";
    		ind = 0;   // 実際の試行回数(負の時は解を得ることができなかった)
    		function main()
    		{
    			str = document.getElementById("func").value + ";";
    					// データの設定
    			let eps1 = 1.0e-10;
    			let eps2 = 1.0e-10;
    			let max  = parseInt(document.getElementById("max").value);
    			let x1   = parseFloat(document.getElementById("x1").value);
    			let x2   = parseFloat(document.getElementById("x2").value);
    			ind      = 0;
    					// 実行
    			let x = secant(x1, x2, max, eps1, eps2, snx);
    					// 結果
    			if (ind < 0)
    				document.getElementById("res").value = "解を求めることができませんでした!";
    			else {
    				let c = 100000;
    				let s1 = Math.round(x * c) / c;
    				document.getElementById("res").value = " x = " + s1 + ", 収束回数:" + ind;
    			}
    		}
    
    		/****************/
    		/* 関数値の計算 */
    		/****************/
    		function snx(x)
    		{
    			let y = eval(str);
    			return y;
    		}
    
    		/*********************************************************/
    		/* secant法(はさみうち法)による非線形方程式f(x)=0の解  */
    		/*      x1,x2 : 初期値(x1 < x2)                        */
    		/*      max : 最大試行回数                               */
    		/*      eps1 : 終了条件1(|x(k+1)-x(k)|<eps1)       */
    		/*      eps2 : 終了条件2(|f(x(k))|<eps2)           */
    		/*      fn : 関数値を計算する関数               */
    		/*      return : 解                                      */
    		/*********************************************************/
    		function secant(x1, x2, max, eps1, eps2, fn)
    		{
    			let f, x = 0.0;
    
    			let count = 0;
    			let f1    = fn(x1);
    			let f2    = fn(x2);
    
    			if (Math.abs(f1) < eps2)
    				x = x1;
    			else {
    				if (Math.abs(f2) < eps2)
    					x = x2;
    				else {
    					while (ind == 0) {
    						count += 1;
    						if (Math.abs(f2-f1) < eps2)
    							ind = -1;
    						else {
    							x = x2 - f2 * (x2 - x1) / (f2 - f1);
    							f = fn(x);
    							if (Math.abs(f) < eps2 || Math.abs(x2-x1) < eps1 || Math.abs(x2-x1) < eps1*Math.abs(x2))
    								ind = count;
    							else {
    								if (count < max) {
    									if (f1*f2 < 0.0) {
    										x2 = x;
    										f2 = f;
    									}
    									else {
    										x1 = x;
    										f1 = f;
    									}
    								}
    								else
    									ind = -1;
    							}
    						}
    					}
    				}
    			}
    
    			return x;
    		}
    	</SCRIPT>
    
    </HEAD>
    
    <BODY STYLE="font-size: 130%; background-color: #eeffee;">
    
    	<H2 STYLE="text-align:center"><B>非線形方程式(セカント法)</B></H2>
    
    	<DL>
    		<DT>  テキストフィールドには,例として,以下に示すような非線形方程式の解を求める場合に対する値が設定されています.他の問題を実行する場合は,それらを適切に修正してください.なお,式は,JavaScript の仕様に適合した形式で記述してあることに注意してください. 
    		<P STYLE="text-align:center"><IMG SRC="secant.gif"></P>
    	</DL>
    
    	<DIV STYLE="text-align:center">
    		初期値:<INPUT ID="x1" STYLE="font-size: 100%" TYPE="text" SIZE="5" VALUE="0">,
    				<INPUT ID="x2" STYLE="font-size: 100%" TYPE="text" SIZE="5" VALUE="1"> 
    		最大繰り返し回数:<INPUT ID="max" STYLE="font-size: 100%" TYPE="text" SIZE="5" VALUE="100"><BR><BR>
    		式:<INPUT ID="func" STYLE="font-size: 100%" TYPE="text" SIZE="50" VALUE="Math.exp(x) - 3.0 * x">= 0  
    		<BUTTON STYLE="font-size: 100%; background-color: pink" onClick="main()">実行</BUTTON><BR><BR>
    		結果:<INPUT ID="res" STYLE="font-size: 100%" TYPE="text" SIZE="30">
    	</DIV>
    
    </BODY>
    
    </HTML>
    			

  4. PHP

    <?php
    
    /*************************************/
    /* セカント法による exp(x)-3x=0 の根 */
    /*      coded by Y.Suganuma          */
    /*************************************/
    /*
              データの設定
    */
    	$eps1 = 1.0e-10;
    	$eps2 = 1.0e-10;
    	$max  = 100;
    	$x1   = 0.0;
    	$x2   = 1.0;
    /*
              実行と結果
    */
    	$x = secant($x1, $x2, $max, $eps1, $eps2, $ind, "snx");
    
    	printf("   ind=%d  x=%f  f= %f\n", $ind, $x, snx($x));
    
    /****************/
    /* 関数値の計算 */
    /****************/
    function snx($x)
    {
    	return exp($x) - 3.0 * $x;
    }
    
    /*********************************************************/
    /* secant法(はさみうち法)による非線形方程式f(x)=0の解  */
    /*      x1,x2 : 初期値(x1 < x2)                        */
    /*      max : 最大試行回数                               */
    /*      eps1 : 終了条件1(|x(k+1)-x(k)|<eps1)       */
    /*      eps2 : 終了条件2(|f(x(k))|<eps2)           */
    /*      ind : > 0 : 収束回数                             */
    /*            =-1 : 収束しなかった                       */
    /*      fun : f(x)を計算する関数名                       */
    /*      return : 解                                      */
    /*********************************************************/
    #include 
    
    function secant($x1, $x2, $max, $eps1, $eps2, &$ind, $fun)
    {
    
    	$x     = 0.0;
    	$count = 0;
    	$ind   = 0;
    	$f1    = $fun($x1);
    	$f2    = $fun($x2);
    
    	if (abs($f1) < $eps2)
    		$x = $x1;
    	else {
    		if (abs($f2) < $eps2)
    			$x = $x2;
    		else {
    			while ($ind == 0) {
    				$count += 1;
    				if (abs($f2-$f1) < $eps2)
    					$ind = -1;
    				else {
    					$x = $x2 - $f2 * ($x2 - $x1) / ($f2 - $f1);
    					$f = $fun($x);
    					if (abs($f) < $eps2 || abs($x2-$x1) < $eps1 || abs($x2-$x1) < $eps1*abs($x2))
    						$ind = $count;
    					else {
    						if ($count < $max) {
    							if ($f1*$f2 < 0.0) {
    								$x2 = $x;
    								$f2 = $f;
    							}
    							else {
    								$x1 = $x;
    								$f1 = $f;
    							}
    						}
    						else
    							$ind = -1;
    					}
    				}
    			}
    		}
    	}
    
    	return $x;
    }
    
    ?>
    			

  5. Ruby

    ############################################
    # セカント法による exp(x)-3x=0 の根
    #      coded by Y.Suganuma
    ############################################
    
    ############################################
    # secant法(はさみうち法)による非線形方程式f(x)=0の解
    #      x1,x2 : 初期値(x1 < x2)
    #      max : 最大試行回数
    #      eps1 : 終了条件1(|x(k+1)-x(k)|<eps1)
    #      eps2 : 終了条件2(|f(x(k))|<eps2)
    #      ind : > 0 : 収束回数
    #            =-1 : 収束しなかった
    #      fn : f(x)を計算する関数名
    #      return : 解
    #      coded by Y.Suganuma
    ############################################
    
    def secant(x1, x2, max, eps1, eps2, ind, &fn) 
    
    	x      = 0.0
    	count  = 0
    	ind[0] = 0
    	f1     = fn.call(x1)
    	f2     = fn.call(x2)
    
    	if f1.abs() < eps2 
    		x = x1
    	else 
    		if f2.abs() < eps2 
    			x = x2
    		else 
    			while ind[0] == 0 
    				count += 1
    				if (f2-f1).abs() < eps2 
    					ind[0] = -1
    				else 
    					x = x2 - f2 * (x2 - x1) / (f2 - f1)
    					f = fn.call(x)
    					if f.abs() < eps2 or (x2-x1).abs() < eps1 or (x2-x1).abs() < eps1*x2.abs() 
    						ind[0] = count
    					else 
    						if count < max 
    							if f1*f2 < 0.0 
    								x2 = x
    								f2 = f
    							else 
    								x1 = x
    								f1 = f
    							end
    						else 
    							ind[0] = -1
    						end
    					end
    				end
    			end
    		end
    	end
    
    	return x
    end
    
    ################
    # 関数値の計算 #
    ################
    snx = Proc.new { |x|
    	Math.exp(x) - 3.0 * x
    }
    
    			# データの設定
    ind  = [0];
    eps1 = 1.0e-10
    eps2 = 1.0e-10
    max  = 100
    x1   = 0.0
    x2   = 1.0
    			# 実行と結果
    x = secant(x1, x2, max, eps1, eps2, ind, &snx)
    
    print("   ind=", ind[0], "  x=", x, "  f= ", snx.call(x), "\n")
    			

  6. Python

    # -*- coding: UTF-8 -*-
    import numpy as np
    from math import *
    
    ############################################
    # secant法(はさみうち法)による非線形方程式f(x)=0の解
    #      x1,x2 : 初期値(x1 < x2)
    #      max : 最大試行回数
    #      eps1 : 終了条件1(|x(k+1)-x(k)|<eps1)
    #      eps2 : 終了条件2(|f(x(k))|<eps2)
    #      ind : > 0 : 収束回数
    #            =-1 : 収束しなかった
    #      fn : f(x)を計算する関数名
    #      return : 解
    #      coded by Y.Suganuma
    ############################################
    
    def secant(x1, x2, max, eps1, eps2, ind, fn) :
    
    	x      = 0.0
    	count  = 0
    	ind[0] = 0
    	f1     = fn(x1)
    	f2     = fn(x2)
    
    	if abs(f1) < eps2 :
    		x = x1
    	else :
    		if abs(f2) < eps2 :
    			x = x2
    		else :
    			while ind[0] == 0 :
    				count += 1
    				if abs(f2-f1) < eps2 :
    					ind[0] = -1
    				else :
    					x = x2 - f2 * (x2 - x1) / (f2 - f1)
    					f = fn(x)
    					if abs(f) < eps2 or abs(x2-x1) < eps1 or abs(x2-x1) < eps1*abs(x2) :
    						ind[0] = count
    					else :
    						if count < max :
    							if f1*f2 < 0.0 :
    								x2 = x
    								f2 = f
    							else :
    								x1 = x
    								f1 = f
    						else :
    							ind[0] = -1
    
    	return x
    
    ################
    # 関数値の計算 #
    ################
    def snx(x) :
    	return exp(x) - 3.0 * x
    
    ############################################
    # セカント法による exp(x)-3x=0 の根
    #      coded by Y.Suganuma
    ############################################
    
    			# データの設定
    ind  = [0];
    eps1 = 1.0e-10
    eps2 = 1.0e-10
    max  = 100
    x1   = 0.0
    x2   = 1.0
    			# 実行と結果
    x = secant(x1, x2, max, eps1, eps2, ind, snx)
    
    print("   ind=" + str(ind[0]) + "  x=" + str(x) + "  f= " + str(snx(x)))
    			

  7. C#

    /*************************************/
    /* セカント法による exp(x)-3x=0 の根 */
    /*      coded by Y.Suganuma          */
    /*************************************/
    using System;
    
    class Program
    {
    	static void Main()
    	{
    		Test1 ts = new Test1();
    	}
    }
    
    class Test1
    {
    	public Test1()
    	{
    	/*
    	          データの設定
    	*/
    		double eps1 = 1.0e-10;
    		double eps2 = 1.0e-10;
    		double x1   = 0.0;
    		double x2   = 1.0;
    		int max     = 100;
    		int ind     = 0;
    	/*
    	          実行と結果
    	*/
    		double x = secant(x1, x2, max, eps1, eps2, ref ind, snx);
    
    		Console.WriteLine("   ind=" + ind + "  x=" + x + "  f=" + snx(x));
    	}
    
    	/****************/
    	/* 関数値の計算 */
    	/****************/
    	double snx(double x)
    	{
    		return Math.Exp(x) - 3.0 * x;
    	}
    
    	/*********************************************************/
    	/* secant法(はさみうち法)による非線形方程式f(x)=0の解  */
    	/*      x1,x2 : 初期値(x1 < x2)                        */
    	/*      max : 最大試行回数                               */
    	/*      eps1 : 終了条件1(|x(k+1)-x(k)|<eps1)       */
    	/*      eps2 : 終了条件2(|f(x(k))|<eps2)           */
    	/*      ind : > 0 : 収束回数                             */
    	/*            =-1 : 収束しなかった                       */
    	/*      fn : 関数値を計算する関数                        */
    	/*      return : 解                                      */
    	/*********************************************************/
    	double secant(double x1, double x2, int max, double eps1, double eps2,
    	              ref int ind, Func<double, double> fn)
    	{
    		double f1 = fn(x1);
    		double f2 = fn(x2);
    		double x  = 0.0;
    		int count = 0;
    		ind = 0;
    
    		if (Math.Abs(f1) < eps2)
    			x = x1;
    		else {
    			if (Math.Abs(f2) < eps2)
    				x = x2;
    			else {
    				while (ind == 0) {
    					count += 1;
    					if (Math.Abs(f2-f1) < eps2)
    						ind = -1;
    					else {
    						x = x2 - f2 * (x2 - x1) / (f2 - f1);
    						double f = fn(x);
    						if (Math.Abs(f) < eps2 ||
    						    Math.Abs(x2-x1) < eps1 || Math.Abs(x2-x1) < eps1*Math.Abs(x2))
    							ind = count;
    						else {
    							if (count < max) {
    								if (f1*f2 < 0.0) {
    									x2 = x;
    									f2 = f;
    								}
    								else {
    									x1 = x;
    									f1 = f;
    								}
    							}
    							else
    								ind = -1;
    						}
    					}
    				}
    			}
    		}
    
    		return x;
    	}
    }
    			

  8. VB

    '''''''''''''''''''''''''''''''''''''
    ' セカント法による exp(x)-3x=0 の根 '
    '      coded by Y.Suganuma          '
    '''''''''''''''''''''''''''''''''''''
    Module Test
    	Sub Main()
    				'
    				' データの設定
    				'
    		Dim eps1 As Double = 1.0e-10
    		Dim eps2 As Double = 1.0e-10
    		Dim x1 As Double   = 0.0
    		Dim x2 As Double   = 1.0
    		Dim max As Integer = 100
    		Dim ind As Integer = 0
    				'
    				' 実行と結果
    				'
    		Dim snx = Function(v) As Double   ' 関数値の計算(ラムダ式)
    	                  Return Math.Exp(v) - 3.0 * v
    	              End Function
    
    		Dim x As Double = secant(x1, x2, max, eps1, eps2, ind, snx)
    
    		Console.WriteLine("   ind=" & ind & " x=" & x & "  f=" & snx(x))
    
    	End Sub
    
    	'''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    	' secant法(はさみうち法)による非線形方程式f(x)=0の解  '
    	'      x1,x2 : 初期値(x1 < x2)                        '
    	'      max : 最大試行回数                               '
    	'      eps1 : 終了条件1(|x(k+1)-x(k)|<eps1)       '
    	'      eps2 : 終了条件2(|f(x(k))|<eps2)           '
    	'      ind : > 0 : 収束回数                             '
    	'            =-1 : 収束しなかった                       '
    	'      fn : 関数値を計算する関数                        '
    	'      return : 解                                      '
    	'''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    	Function secant(x1 As Double, x2 As Double, max As Integer, eps1 As Double,
    	                eps2 As Double, ByRef ind As Integer,
    	                fn As Func(Of Double, Double))
    
    		Dim f1 As Double     = fn(x1)
    		Dim f2 As Double     = fn(x2)
    		Dim x As Double      = 0.0
    		Dim count As Integer = 0
    		ind = 0
    
    		If Math.Abs(f1) < eps2
    			x = x1
    		Else
    			If Math.Abs(f2) < eps2
    				x = x2
    			Else
    				Do While ind = 0
    					count += 1
    					If Math.Abs(f2-f1) < eps2
    						ind = -1
    					Else
    						x = x2 - f2 * (x2 - x1) / (f2 - f1)
    						Dim f As Double = fn(x)
    						If Math.Abs(f) < eps2 or
    						   Math.Abs(x2-x1) < eps1 or Math.Abs(x2-x1) < eps1*Math.Abs(x2)
    							ind = count
    						Else
    							If count < max
    								If f1*f2 < 0.0
    									x2 = x
    									f2 = f
    								Else
    									x1 = x
    									f1 = f
    								End If
    							Else
    								ind = -1
    							End If
    						End If
    					End If
    				Loop
    			End If
    		End If
    
    		Return x
    
    	End Function
    
    End Module
    			

情報学部 菅沼ホーム 目次 索引