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

第6章 関数

  1. 6.1 関数
    1. A. C++
    2. B. Java
    3. C. JavaScript
    4. D. PHP
    5. E. Ruby
    6. F. Python
    7. G. C#
    8. H. VB
  2. 6.2 関数に対するプログラム例
    1. A. C++
    2. B. Java
    3. C. JavaScript
    4. D. PHP
    5. E. Ruby
    6. F. Python
    7. G. C#
    8. H. VB

6.1 関数

  関数は,一連の手続きをまとめたプログラムの塊であり,外部から与えられた情報に基づき,何らかの処理を行い,関数を呼び出したプログラムにその結果を返します(結果を返さない関数も存在する).いずれの言語にも,関数に対応する手続きの塊は存在しますが,言語によって,呼び方が異なる場合があります.後に述べるクラスに含まれるものをメソッド,含まれないものを関数と呼ぶ場合が多いようですが,その機能はほとんど同じです.従って,ここでは,誤解が生じないようであれば,すべて,関数と呼んでいきます.あえて,区別したいような場合は,メソッドやメンバー関数という言葉を利用します.

  関数を呼び出した側から,関数に情報を渡す手段として最も一般的な方法は引数です.例えば,あるプログラムから関数 func を呼ぶ場合,C/C++ の場合,
x = func(a, b, c);		
のように記述し,関数 func の定義は,
int func(int x, int y, double z) {
   ・・・・・
}		
のようにして行います.このとき,括弧内に記述された変数のリストを引数と呼びます.引数を通して渡された情報に基づき,関数 func は,何らかの処理を行い,その結果を返します.上の例においては,返された結果を変数 x に代入しています.引数以外の方法によって,関数に情報を伝達する方法も存在しますが,ここでは割愛します.「第8章 変数の有効範囲(スコープ)」を参照してください.

  一般に,関数を呼び出す際,引数として与えられた a,b,c に記憶されているデータのコピーが変数 x,y,z に渡され,その情報に基づき関数内における処理が実行されます.コピーが渡されるため,関数 func 内において,変数 x,y,z の値が変更されても,関数を呼び出した側の変数 a,b,c の値は変化しません.このことによって,関数内において誤ってデータを変更しても,関数を呼び出した側はその影響を受けないことになります.しかし,引数としてポインタ(アドレス)が渡された場合は,いかにコピーされた値であっても,そのポインタが指す場所は,関数を呼んだ側と関数内において同じ場所を指すことになります.従って,その場所のデータを変更することはいずれの側においても可能になります.例えば,C++ において,配列とポインタは非常に強い関係があり,配列を引数とすることはポインタ(アドレス)を引数とすることに相当し,関数側においても,また,関数を呼んだ側においても同じ配列を修正することができます.C++ においては,関数側で関数を呼んだ側のデータを修正できるか否かは,その記述方法によって明確に識別できます.しかし,他のプログラミング言語においては,あまり明確ではありません.次節におけるプログラム例においては,関数内におけるデータの修正が関数を呼び出した側に影響を与える否かといった点に重点を置いて,説明していきたいと思います.

  また,場合によっては,関数名を引数としたい場合があります.例えば,ニュートン法によって,非線形方程式 f(x) = 0 の根を求める関数を作成したいとします.ニュートン法は,
xn+1 = xn - f(xn) / f'(xn)		
を繰り返すことによって,非線形方程式の解を求める方法です.ニュートン法によって解を求めるアルゴリズムは,非線形方程式が異なっても変わりません.しかし,f(x) やその微分を計算するアルゴリズムは非線形方程式によって異なってきます.このようなとき,f(x) やその微分の計算を別の関数で行い,その関数名を非線形方程式の解を求める関数に渡すように作成すれば,非線形方程式が変わっても,同じニュートン法によって解を求める関数を利用できます.

  似たような問題として,ソート(並べ替え)を行う関数があります.ソートを実行するためには,データどうしの比較を行う必要があります.基本的な関係演算子 <,> 等によって比較可能な場合はそれほど問題がありませんが,扱うデータ型によっては,特殊な比較演算を行なわなければならない場合があります.そのような場合においても,比較を行う関数名を引数としてソートを実行する関数に渡してやることが可能であれば,どのようなデータ型に対しても同じソートを実行する関数を利用できます.次節におけるプログラム例においては,上に述べた引数に対する値の変化と共に,関数名を引数とする方法についても説明していきたいと思います.

  1. C++

      関数の一般的定義方法は以下に示すとおりです.
    関数の型 関数名 (引数リスト) {
    	・・・・・
    	・・・・・
    }			
      アドレス渡し,参照渡しを明確に区別でき,引数が省略された場合のデフォルト値を設定可能なデフォルト引数も利用できます.また,引数の数や型が異なる場合は,同じ名前の関数を定義でき(関数名のオーバーロード),実行時に適切な関数が使用されます.下に示す例において,17 行目,18 行目に対しては 07 行目~ 09 行目の関数,また,19 行目に対しては 11 行目~ 13 行目の関数が使用されます.また,18 行目,19 行目においては,2 番目の引数が省略されていますので,07 行目,11 行目に定義されているデフォルト値が使用されます.このプログラムを実行すると,その下に示すような結果が得られます.
    01	/******************************************/
    02	/* デフォルト引数と関数名のオーバーロード */
    03	/*      coded by Y.Suganuma               */
    04	/******************************************/
    05	#include <stdio.h>
    06	
    07	int add(int a, int b = 0) {
    08		return a + b;
    09	}
    10	
    11	double add(double a, double b = 3.5) {
    12		return a + b;
    13	}
    14	
    15	int main()
    16	{
    17		printf("整数 1 + 2 = %d\n", add(1, 2));
    18		printf("整数 1 + 0 = %d\n", add(1));
    19		printf("実数 1.0 + 3.5 = %f\n", add(1.0));
    20	
    21		return 0;
    22	}
    			
    整数 1 + 2 = 3
    整数 1 + 0 = 1
    実数 1.0 + 3.5 = 4.500000			

  2. Java

      関数の一般的定義方法は以下に示すとおりです.メソッドと関数は,ほぼ,同じ意味です.
    [メソッド修飾子] メソッドの型 メソッド名 (引数リスト) {
    	・・・・・
    	・・・・・
    }			
      引数の数や型が異なる場合は,同じ名前の関数を定義でき(関数名のオーバーロード),実行時に適切な関数が使用されます.下に示す例において,10 行目に対しては 14 行目~ 16 行目の関数,また,11 行目に対しては 18 行目~ 20 行目の関数が使用されます.このプログラムを実行すると,その下に示すような結果が得られます.
    01	/****************************/
    02	/* 関数名のオーバーロード   */
    03	/*      coded by Y.Suganuma */
    04	/****************************/
    05	import java.io.*;
    06	
    07	public class Test {
    08		public static void main(String args[]) throws IOException
    09		{
    10			System.out.printf("整数 %d\n", add(1, 2));
    11			System.out.printf("実数 %f\n", add(1.0));
    12		}
    13	
    14		static int add(int a, int b) {
    15			return a + b;
    16		}
    17	
    18		static double add(double a) {
    19			return a + 3.5;
    20		}
    21	}
    			
    整数 1 + 2 = 3
    実数 1.0 + 3.5 = 4.500000			

  3. JavaScript

      関数の一般的定義方法は以下に示すとおりです.
    function 関数名 (引数リスト) {
    	・・・・・
    	・・・・・
    }			
      引数が省略された場合のデフォルト値を設定可能なデフォルト引数を利用できます.下に示す例の 13 行目においては,2 番目の引数が省略されていますので,18 行目に定義されているデフォルト値が使用されます.このプログラムを実行すると,以下に示すような結果が得られます.なお,ここをクリックし,表示された画面の「 OK 」ボタンをクリックすれば,結果と以下に示したソースプログラムを見ることができます.
    01	<!DOCTYPE HTML>
    02	<HTML>
    03	<HEAD>
    04		<TITLE>関数</TITLE>
    05		<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
    06		<SCRIPT TYPE="text/javascript">
    07			/****************************/
    08			/* デフォルト引数           */
    09			/*      coded by Y.Suganuma */
    10			/****************************/
    11			function run() {
    12				let str = "1 + 2 = " + add(1, 2) + "\n";
    13				str    += "1 + 5 = " + add(1) + "\n";
    14					// 結果の設定
    15				document.getElementById("tx").value = str;
    16			}
    17	
    18			function add(a, b = 5) {
    19				return a + b;
    20			}
    21		</SCRIPT>
    22	</HEAD>
    23	<BODY  STYLE="font-size:130%">
    24		<P STYLE="text-align:center">
    25			<INPUT TYPE="button" VALUE="OK" onClick="run()" STYLE="font-size:90%"><BR><BR>
    26			<TEXTAREA TYPE="text" ID="tx" COLS="10" ROWS="3" STYLE="font-size: 100%"></TEXTAREA>
    27		</P>
    28	</BODY>
    29	</HTML>
    			
    1 + 2 = 3
    1 + 5 = 6			

  4. PHP

      関数の一般的定義方法は以下に示すとおりです.
    function 関数名 (引数リスト) {
    	・・・・・
    	・・・・・
    }			
      PHP においては,参照渡しが可能です.特に,PHP の場合は,このコンテンツで説明している他の言語とは異なり,配列を引数とした場合においても,各要素を含めたすべてのコピーが渡されるため,関数内で引数で渡された配列の要素の値を変更しても,関数を呼んだ側の配列に影響を与えません.関数を呼んだ側における配列の要素の値も変更したい場合は,参照渡しを利用する必要があります.

      引数が省略された場合のデフォルト値を設定可能なデフォルト引数を利用できます.下に示す例の 11 行目においては,2 番目の引数が省略されていますので,06 行目に定義されているデフォルト値が使用されます.このプログラムを実行すると,その下に示すような結果が得られます.
    01	<?php
    02		/****************************/
    03		/* デフォルト引数           */
    04		/*      coded by Y.Suganuma */
    05		/****************************/
    06		function add($a, $b = 5) {
    07			return $a + $b;
    08		}
    09	
    10		printf("1 + 2 = %d\n", add(1, 2));
    11		printf("1 + 5 = %d\n", add(1));
    12	?>
    			
    1 + 2 = 3
    1 + 5 = 6			

  5. Ruby

      関数の一般的定義方法は以下に示すとおりです.メソッドと関数は,ほぼ,同じ意味です.
    def メソッド名 [引数の並び]
    	・・・・・
    	・・・・・
    end			
      引数が省略された場合のデフォルト値を設定可能なデフォルト引数を利用できます.下に示す例の 10 行目においては,2 番目の引数が省略されていますので,05 行目に定義されているデフォルト値が使用されます.このプログラムを実行すると,その下に示すような結果が得られます.
    01	#***************************/
    02	# デフォルト引数           */
    03	#      coded by Y.Suganuma */
    04	#***************************/
    05	def add(a, b = 5)
    06		return a + b;
    07	end
    08	
    09	printf("1 + 2 = %d\n", add(1, 2));
    10	printf("1 + 5 = %d\n", add(1));
    			
    1 + 2 = 3
    1 + 5 = 6			

  6. Python

      関数の一般的定義方法は以下に示すとおりです.
    def 関数名 (引数リスト) : 
    	・・・・・
    	・・・・・			
      引数が省略された場合のデフォルト値を設定可能なデフォルト引数を利用できます.下に示す例の 10 行目においては,2 番目の引数が省略されていますので,06 行目に定義されているデフォルト値が使用されます.このプログラムを実行すると,その下に示すような結果が得られます.
    01	# -*- coding: UTF-8 -*-
    02	#***************************/
    03	# デフォルト引数           */
    04	#      coded by Y.Suganuma */
    05	#***************************/
    06	def add(a, b = 5) :
    07		return a + b
    08	
    09	print("1 + 2 = ", add(1, 2))
    10	print("1 + 5 = ", add(1))
    			
    1 + 2 = 3
    1 + 5 = 6			

  7. C#

      関数の一般的定義方法は以下に示すとおりです.
    関数の型 関数名 (引数リスト) {
    	・・・・・
    	・・・・・
    }			
      引数が省略された場合のデフォルト値を設定可能なデフォルト引数を利用できます.また,引数の数や型が異なる場合は,同じ名前の関数を定義でき(関数名のオーバーロード),実行時に適切な関数が使用されます.下に示す例において,11 行目,12 行目に対しては 16 行目~ 18 行目の関数,また,13 行目に対しては 20 行目~ 22 行目の関数が使用されます.また,12 行目,13 行目においては,2 番目の引数が省略されていますので,16 行目,20 行目に定義されているデフォルト値が使用されます.このプログラムを実行すると,その下に示すような結果が得られます.
    01	/******************************************/
    02	/* 関数名のオーバーロードとデフォルト引数 */
    03	/*      coded by Y.Suganuma               */
    04	/******************************************/
    05	using System;
    06	
    07	class Program
    08	{
    09		static void Main()
    10		{
    11			Console.WriteLine("整数 1 + 2 = " + add(1, 2));
    12			Console.WriteLine("整数 1 + 0 = " + add(1));
    13			Console.WriteLine("実数 1 + 3.5 = " + add(1.0));
    14		}
    15	
    16		static int add(int a, int b = 0) {
    17			return a + b;
    18		}
    19	
    20		static double add(double a, double b = 3.5) {
    21			return a + b;
    22		}
    23	}
    			
    整数 1 + 2 = 3
    整数 1 + 0 = 1
    実数 1.0 + 3.5 = 4.5			

  8. VB

      関数の一般的定義方法は以下に示すとおりです.
    Function 関数名 (引数リスト) As 戻り値のデータ型   // 戻り値がある場合
    	・・・・・
    	・・・・・
    	Return ...
    End Function			
    Sub 関数名 (引数リスト)   // 戻り値がない場合
    	・・・・・
    	・・・・・
    End Sub			
      引数が省略された場合のデフォルト値を設定可能なデフォルト引数を利用できます.また,引数の数や型が異なる場合は,同じ名前の関数を定義でき(関数名のオーバーロード),実行時に適切な関数が使用されます.下に示す例において,07 行目,08 行目に対しては 12 行目~ 14 行目の関数,また,09 行目に対しては 16 行目~ 18 行目の関数が使用されます.また,07 行目,08 行目においては,2 番目の引数が省略されていますので,12 行目,16 行目に定義されているデフォルト値が使用されます.このプログラムを実行すると,その下に示すような結果が得られます.
    01	''''''''''''''''''''''''''''''''''''''''''
    02	' 関数名のオーバーロードとデフォルト引数 '
    03	'      coded by Y.Suganuma               '
    04	''''''''''''''''''''''''''''''''''''''''''
    05	Module Test
    06		Sub Main()
    07			Console.WriteLine("整数 1 + 2 = " & add(1, 2))
    08			Console.WriteLine("整数 1 + 0 = " & add(1))
    09			Console.WriteLine("実数 1 + 3.5 = " & add(1.0))
    10		End Sub
    11	
    12		Function add(a As Integer, Optional b As Integer = 0) As Integer
    13			Return a + b
    14		End Function
    15	
    16		Function add(a As Double, Optional b As Double = 3.5) As Double
    17			Return a + b
    18		End Function
    19	End Module
    			
    整数 1 + 2 = 3
    整数 1 + 0 = 1
    実数 1.0 + 3.5 = 4.5			

6.2 関数に対するプログラム例

  1. C++

    1. 基本型データ
      01	#include <stdio.h>
      02	
      03	/**********************************/
      04	/* 2 つの整数の和                 */
      05	/*      u, v : 和を計算するデータ */
      06	/*      w : u + v                 */
      07	/*      x : u + v                 */
      08	/*      return : u + v            */
      09	/**********************************/
      10	int func1(int u, int v, int *w, int &x)
      11	{
      12		u     = 100;
      13		int a = u + v;
      14		*w    = a;
      15		x     = a;
      16		return a;
      17	}
      18	
      19	int main()
      20	{
      21		printf("基本型\n");
      22		int a1 = 10, b1 = 20, c1 = 0, d1 = 0, e1 = 0;
      23		printf("   前 %d %d %d %d %d\n", a1, b1, c1, d1, e1);
      24		c1 = func1(a1, b1, &d1, e1);
      25		printf("   後 %d %d %d %d %d\n", a1, b1, c1, d1, e1);
      26	
      27		return 0;
      28	}
      				
        基本型データを関数の引数とした場合の例です.10 行目と 24 行目から明らかなように,変数 a1,b1 はその値,変数 d1 はそのアドレス,また,変数 e1 に関しては参照渡しをしており,24 行目の変数 c1 には,関数の戻り値が代入されます.このプログラム内の出力文によって,以下に示すような結果が得られます.この結果は,関数を呼ぶ前と呼んだ後における変数 a1,b1,c1,d1,及び,e1 の値を示しています.
      基本型
         前 10 20 0 0 0
         後 10 20 120 120 120					
        12 行目において,変数 u (変数 a1 のコピー)の値を変更していますが,変数 a1 はその影響を受けていません.しかし,そのアドレスを渡した変数 d1,及び,参照渡しをした変数 e1 は,14 行目,及び,15 行目の処理によって,その値が変化しています.当然,16 行目の return 文による戻り値を代入した変数 c1 の値も変化します.
    2. 1 次元配列
      01	#include <stdio.h>
      02	#include <vector>
      03	
      04	using namespace std;
      05	
      06	/************************/
      07	/* 1 次元配列の要素の和 */
      08	/*      n : 要素数      */
      09	/*      u, v : 配列     */
      10	/*      w : vector      */
      11	/*      return wの和    */
      12	/************************/
      13	int func2(int n, int *u, int *v, vector<int> w)   // func2(int n, int u[], int v[], vector<int> w)
      14	{
      15		for (int i1 = 0; i1 < n; i1++) {
      16			u[n] += u[i1];
      17			v[n] += v[i1];
      18			w[n] += w[i1];
      19		}
      20		return w[n];
      21	}
      22	
      23	int main()
      24	{
      25		printf("1 次元配列\n");
      26		int a2[] = {1, 2, 3, 0};
      27		int *b2  = new int [4];
      28		for (int i1 = 0; i1 < 3; i1++)
      29			b2[i1] = 10 * (i1 + 1);
      30		b2[3] = 0;
      31		vector<int> c2;
      32		for (int i1 = 0; i1 < 3; i1++)
      33			c2.push_back(10 * (i1 + 1));
      34		c2.push_back(0);
      35		printf("   前 a2 %d %d %d %d\n", a2[0], a2[1], a2[2], a2[3]);
      36		printf("   前 b2 %d %d %d %d\n", b2[0], b2[1], b2[2], b2[3]);
      37		printf("   前 c2 %d %d %d %d\n", c2[0], c2[1], c2[2], c2[3]);
      38		int d2 = func2(3, a2, b2, c2);
      39		printf("   後 a2 %d %d %d %d\n", a2[0], a2[1], a2[2], a2[3]);
      40		printf("   後 b2 %d %d %d %d\n", b2[0], b2[1], b2[2], b2[3]);
      41		printf("   後 c2 %d %d %d %d d2 %d\n", c2[0], c2[1], c2[2], c2[3], d2);
      42	
      43		return 0;
      44	}
      				
        1 次元配列を関数の引数とした場合の例です.文字列も 1 次元配列ですので,配列と同じ結果が得られます.ただし,string クラスのオブジェクトである場合は,vector クラスのオブジェクトと同じ結果になります.関数に対して,0 以外の値が入っている要素の数( 3 ),通常の 1 次元配列( a2 ),new 演算子による 1 次元配列( b2 ),及び,vector クラスのオブジェクト( c2 )を引数として渡しています.配列の場合は,記憶領域のアドレスが渡されることと同等ですので,関数内においてその各要素の値を変更可能です.そのため,1 番目から 3 番目までの要素の和を 4 番目の要素に記憶しています.しかし,vector クラスの場合は,その内容がコピーされて渡されるため,関数を呼んだ側における 4 番目の要素の値を修正できません( 18 行目と 41 行目に対する出力結果参照).従って,関数の戻り値として返し,変数 d2 に代入しています.勿論,vector クラスのオブジェクトに対し,アドレス渡しや参照渡しをすれば,関数内においてその値を変更できます.このプログラム内の出力文によって,以下に示すような結果が得られます.
      1 次元配列
         前 a2 1 2 3 0
         前 b2 10 20 30 0
         前 c2 10 20 30 0
         後 a2 1 2 3 6
         後 b2 10 20 30 60
         後 c2 10 20 30 0 d2 60					
    3. 2 次元配列
      01	#include <stdio.h>
      02	
      03	/********************************/
      04	/* 2 次元配列の要素の和         */
      05	/*      n : 行数                */
      06	/*      m : 列数                */
      07	/*      u,v,w : 配列            */
      08	/*      return : 和を入れる配列 */
      09	/********************************/
      10	int *func3(int n, int m, int u[][4], int *v, int **w)
      11	{
      12		int *s = new int [3];
      13		for (int i1 = 0; i1 < 3; i1++)
      14			s[i1] = 0;
      15		for (int i1 = 0; i1 < n; i1++) {
      16			for (int i2 = 0; i2 < m-1; i2++) {
      17				u[i1][3] += u[i1][i2];
      18				s[0]     += u[i1][i2];
      19				s[1]     += v[i1 * m + i2];
      20				s[2]     += w[i1][i2];
      21			}
      22		}
      23		return s;
      24	}
      25	
      26	int main()
      27	{
      28		printf("2 次元配列\n");
      29		int a3[][4] = {{1, 2, 3, 0}, {4, 5, 6, 0}};
      30		int **b3    = new int *[2];
      31		for (int i1 = 0; i1 < 2; i1++) {
      32			b3[i1] = new int [3];
      33			for (int i2 = 0; i2 < 3; i2++)
      34				b3[i1][i2] = 30 * i1 + 10 * (i2 + 1);
      35		}
      36		printf("   a3 %d %d %d %d\n", a3[0][0], a3[0][1], a3[0][2], a3[0][3]);
      37		printf("      %d %d %d %d\n", a3[1][0], a3[1][1], a3[1][2], a3[1][3]);
      38		printf("   b3 %d %d %d\n", b3[0][0], b3[0][1], b3[0][2]);
      39		printf("      %d %d %d\n", b3[1][0], b3[1][1], b3[1][2]);
      40		int *c3 = func3(2, 4, a3, &a3[0][0], b3);
      41		printf("   a3[0][3],a3[1][3] %d %d\n", a3[0][3], a3[1][3]);
      42		printf("   c3 %d %d %d\n", c3[0], c3[1], c3[2]);
      43	
      44		return 0;
      45	}
      				
        2 次元配列を関数の引数とした場合の例です.関数に対して,行の数( 2 ),列の数( 4 ),通常の 2 次元配列( a3,2 行 4 列 ),a3 に対するデータが記憶されている領域の先頭アドレス( &a3[0][0],1 次元配列とみなされる),new 演算子による 2 次元配列( b3,2 行 3 列 ) を引数として渡しています.関数内において,u,v,及び,w における各要素の和を計算し,その結果を 1 次元配列 s に入れて返しています.また,u( a3 )の各行の和を,u[0][3],u[1][3] に代入しています.

        通常の多次元配列を引数として送る場合,10 行目に示すように,配列の大きさを示す一番左の部分は省略可能ですが,それ以外の部分は省略できません( u[][4] ).従って,配列の大きさを変更したいような場合は,関数を呼び出す側はもちろん,関数側のプログラムも変更してやる必要があります.しかし,通常の配列の場合,多次元配列であっても,各要素は連続した領域に記憶されます.従って,その先頭アドレスを渡してやることによって,多次元配列を 1 次元配列として取り扱うことが可能になります.その際,19 行目に示すように,2 次元配列の列の数を m とすると,2 次元配列の i 行 j 列要素は,1 次元配列の( i * m + j )要素に対応することになります(3 次元以上の配列に対しても可能).このようにすれば,配列の大きさを変更したい場合にも,関数を呼ぶ側のプログラムの修正だけですみます.このプログラム内の出力文によって,以下に示すような結果が得られます.
      2 次元配列
         a3 1 2 3 0
            4 5 6 0
         b3 10 20 30
            40 50 60
         a3[0][3],a3[1][3] 6 15
         c3 21 21 210					
    4. クラスのオブジェクト
      01	#include <stdio.h>
      02	
      03	/******************/
      04	/* クラス Example */
      05	/******************/
      06	class Example {
      07		public :
      08			int n;
      09			int x[3];
      10			int *y;
      11			Example(int n1)
      12			{
      13				n = n1;
      14				for (int i1 = 0; i1 < 3; i1++)
      15					x[i1] = i1;
      16				y = new int [n];
      17				for (int i1 = 0; i1 < n; i1++)
      18					y[i1] = i1;
      19			}
      20	};
      21	
      22	/************************/
      23	/* オブジェクトの値変更 */
      24	/*      x1 : コピー     */
      25	/*      x2 : アドレス   */
      26	/*      x3 : 参照       */
      27	/************************/
      28	void func4(Example x1, Example *x2, Example &x3)
      29	//void func4(const Example x1, const Example *x2, const Example &x3)
      30	{
      31		x1.n  = 4;
      32		x2->n = 5;
      33		x3.n  = 6;
      34		x1.x[0] = 4;
      35		x1.y[0] = 4;   // const 指定でも可
      36		x2->x[0] = 5;
      37		x2->y[0] = 5;   // const 指定でも可
      38		x3.x[0] = 6;
      39		x3.y[0] = 6;   // const 指定でも可
      40	}
      41	
      42	int main()
      43	{
      44		printf("オブジェクト\n");
      45		Example a4(3);
      46		Example a5(3);   // Example *a5 = new Example(3);
      47		Example a6(3);
      48		printf("   前 a4 n %d\n", a4.n);
      49		printf("      x %d %d %d\n", a4.x[0], a4.x[1], a4.x[2]);
      50		printf("      y %d %d %d\n", a4.y[0], a4.y[1], a4.y[2]);
      51		printf("   前 a5 n %d\n", a5.n);
      52		printf("      x %d %d %d\n", a5.x[0], a5.x[1], a5.x[2]);
      53		printf("      y %d %d %d\n", a5.y[0], a5.y[1], a5.y[2]);
      54	//	printf("   前 a5 n %d\n", a5->n);
      55	//	printf("      x %d %d %d\n", a5->x[0], a5->x[1], a5->x[2]);
      56	//	printf("      y %d %d %d\n", a5->y[0], a5->y[1], a5->y[2]);
      57		printf("   前 a6 n %d\n", a6.n);
      58		printf("      x %d %d %d\n", a6.x[0], a6.x[1], a6.x[2]);
      59		printf("      y %d %d %d\n", a6.y[0], a6.y[1], a6.y[2]);
      60		func4(a4, &a5, a6);   // func4(a4, a5, a6);
      61		printf("   後 a4 n %d\n", a4.n);
      62		printf("      x %d %d %d\n", a4.x[0], a4.x[1], a4.x[2]);
      63		printf("      y %d %d %d\n", a4.y[0], a4.y[1], a4.y[2]);
      64		printf("   後 a5 n %d\n", a5.n);
      65		printf("      x %d %d %d\n", a5.x[0], a5.x[1], a5.x[2]);
      66		printf("      y %d %d %d\n", a5.y[0], a5.y[1], a5.y[2]);
      67	//	printf("   後 a5 n %d\n", a5->n);
      68	//	printf("      x %d %d %d\n", a5->x[0], a5->x[1], a5->x[2]);
      69	//	printf("      y %d %d %d\n", a5->y[0], a5->y[1], a5->y[2]);
      70		printf("   後 a6 n %d\n", a6.n);
      71		printf("      x %d %d %d\n", a6.x[0], a6.x[1], a6.x[2]);
      72		printf("      y %d %d %d\n", a6.y[0], a6.y[1], a6.y[2]);
      73	
      74		return 0;
      75	}
      				
        クラスのオブジェクト(クラスの定義は,06 行目~ 20 行目)を関数の引数とした場合の例です.クラスのオブジェクト( a4 ),オブジェクトのアドレス( &a5 ),及び,オブジェクトの参照( a6 )を引数として渡しています.クラスのオブジェクトの場合であっても,基本的に,そのデータすべてがコピーされて関数に渡されます.特に,大きなオブジェクトを引数として渡す場合,そのコピーのために時間がかかってしまいます.アドレス渡し,または,参照渡しによって,そのオーバーヘッドを避けることができます.しかし,アドレス渡し,または,参照渡しを行えば,関数側で関数を呼んだ側のオブジェクトの値を変更することが可能になります.それを許可したくない場合は,29 行目に示すように,const 指定を行う必要があります.なお,オブジェクト a5 を new 演算子を使用して生成し( 46 行目のコメント),それを関数の引数としても( 60 行目のコメント),同様の結果が得られます.ただし,a5 に対する出力文を,54 行目~ 56 行目,67 行目~ 69 行目のように変更する必要があります.このプログラム内の出力文によって,下の枠内に示すような結果が得られます.

        a4 に対する関数を呼ぶ前と後の出力結果を見てください.31 行目,34 行目において,クラス内に定義されている変数 n と 配列 x の要素 x[0] の値を変更しているにもかかわらず,a4 に対応する値は変化していません( a5,a6 の対応する値は変化).これは,a4 のコピーが関数に渡されていることを意味しています.しかし,new 演算子によって生成された配列の y[0] の値は,35 行目の操作によって変化しています.これは,オブジェクトのコピーにおいて,配列 y の記憶場所を示すアドレスはコピーされますが,アドレスが指す内容まではコピーされないことを意味しています.const 指定を行っても,変数 n や x[i] の変更は不可能になりますが,y[i] の変更は可能なままですので,十分注意してください( a5,a6 についても同様).全体における整合性を保ち,かつ,プログラムミングにおける誤りを避けるためには,クラスのオブジェクトを引数として渡す場合(アドレス渡しや参照渡しでない場合)は,アドレスが指すデータ部分もコピーして渡すように,また,const 指定を行えば,アドレスが指す部分も変更不可能になるように仕様を変更すべきではないでしょうか.
      (出力)
      オブジェクト
         前 a4 n 3
            x 0 1 2
            y 0 1 2
         前 a5 n 3
            x 0 1 2
            y 0 1 2
         前 a6 n 3
            x 0 1 2
            y 0 1 2
         後 a4 n 3
            x 0 1 2
            y 4 1 2
         後 a5 n 5
            x 5 1 2
            y 5 1 2
         後 a6 n 6
            x 6 1 2
            y 6 1 2
      				
    5. 関数名( sort )
      01	#include <stdio.h>
      02	#include <functional>
      03	#include <algorithm>
      04	
      05	using namespace std;
      06	
      07	/*****************************/
      08	/* データの比較(昇順)      */
      09	/* a > bの場合に0以外(真) */
      10	/*****************************/
      11	bool ascend(int a, int b)
      12	{
      13		return a < b;
      14	}
      15	
      16	/*****************************/
      17	/* データの比較(降順)      */
      18	/* a < bの場合に0以外(真) */
      19	/*****************************/
      20	bool descend(int a, int b)
      21	{
      22		return a > b;
      23	}
      24	
      25	/*****************************************************************/
      26	/* バブルソート                                                  */
      27	/*      n : データの数                                           */
      28	/*      data : データ                                            */
      29	/*      compare : 比較を行う関数                                 */
      30	/* バブルソートの手順                                            */
      31	/*     1)配列data[i]にn個のデータが入っているものとする.   */
      32	/*        i=0,1,・・・,n-1                                  */
      33	/*     2)i番目のデータとi+1番目のデータを比較し,もし,     */
      34	/*        data[i+1] < data[i] (昇順の場合)            */
      35	/*      であればそれらのデータを交換する. i=0,1,・・・,n-2  */
      36	/*        →この結果,data[n-1]に最も大きなデータが入る  */
      37	/*              ことになる                                       */
      38	/*     3)次に,n-1個のデータに対し上の処理を繰り返す.      */
      39	/*     4)同様に,n-2,n-3,・・・個のデータに対して同じ処理 */
      40	/*        を繰り返す                                             */
      41	/*****************************************************************/
      42	//void func5(int n, int *data, less<int> compare)   // 関数オブジェクト
      43	//void func5(int n, int *data, auto compare)   // ラムダ式
      44	void func5(int n, int *data, bool (*compare)(int, int))
      45	{
      46		int sw = 0;
      47	
      48		if (n > 1) {
      49			for (int i1 = 0; i1 < n-1; i1++) {
      50				if (!compare(data[i1], data[i1+1])) {
      51					sw = 1;
      52					swap(data[i1], data[i1+1]);
      53				}
      54			}
      55		}
      56	
      57		if (sw > 0)
      58			func5(n-1, data, compare);
      59	}
      60	
      61	int main()
      62	{
      63		printf("関数名(sort)\n");
      64		int a7[] = {3, 2, 5, 4, 1};
      65		int a8[] = {3, 2, 5, 4, 1};
      66		printf("   前(a7) %d %d %d %d %d\n", a7[0], a7[1], a7[2], a7[3], a7[4]);
      67		printf("   前(a8) %d %d %d %d %d\n", a8[0], a8[1], a8[2], a8[3], a8[4]);
      68		func5(5, a7, ascend);   // 昇順
      69		func5(5, a8, descend);   // 降順
      70		printf("   後(a7,昇順) %d %d %d %d %d\n", a7[0], a7[1], a7[2], a7[3], a7[4]);
      71		printf("   後(a8,降順) %d %d %d %d %d\n", a8[0], a8[1], a8[2], a8[3], a8[4]);
      72		printf("関数オブジェクト,ラムダ式\n");
      73		int a9[] = {3, 2, 5, 4, 1};
      74		int a10[] = {3, 2, 5, 4, 1};
      75		printf("   前( a9) %d %d %d %d %d\n", a9[0], a9[1], a9[2], a9[3], a9[4]);
      76		printf("   前(a10) %d %d %d %d %d\n", a10[0], a10[1], a10[2], a10[3], a8[4]);
      77	//	func5(5, a9, less<int>());   // 昇順,関数オブジェクト
      78	//	func5(5, a10, [](int x, int y){ return x > y; });   // 降順,ラムダ式
      79		sort(a9, a9+5, less<int>());   // 昇順,関数オブジェクト
      80		sort(a10, a10+5, [](int x, int y){ return x > y; });   // 降順,ラムダ式
      81		printf("   後( a9,昇順,関数オブジェクト) %d %d %d %d %d\n", a9[0], a9[1], a9[2], a9[3], a9[4]);
      82		printf("   後(a10,降順,ラムダ式) %d %d %d %d %d\n", a10[0], a10[1], a10[2], a10[3], a8[4]);
      83	
      84		return 0;
      85	}
      				
        関数名を関数の引数とした場合の例です.68,69 行目においては,バブルソートを行う関数 func5 に,データの数( 5 ),ソートすべきデータ( a7,a8 ),及び,比較を実行するための関数名( ascend,descend )を引数として渡しています.

        また,関数に対する引数として,関数オブジェクトラムダ式を使用することも可能です.上の問題にそのまま適用すると,77,78 行目に対応して,関数 func5 も,42,43 行目のように修正する必要があります.そこで,アルゴリズム内の関数 sort を使用した例を,79,80 行目に挙げておきます.このプログラム内の出力文によって,以下に示すような結果が得られます.正しくソートが行われているのが分かると思います.
      関数名(sort)
         前(a7) 3 2 5 4 1
         前(a8) 3 2 5 4 1
         後(a7,昇順) 1 2 3 4 5
         後(a8,降順) 5 4 3 2 1
      関数オブジェクト,ラムダ式
         前( a9) 3 2 5 4 1
         前(a10) 3 2 5 4 1
         後( a9,昇順,関数オブジェクト) 1 2 3 4 5
         後(a10,降順,ラムダ式) 5 4 3 2 1					
    6. 関数名(ニュートン法)
      01	#include <stdio.h>
      02	#include <math.h>
      03	
      04	/************************/
      05	/* 関数値(f(x))の計算 */
      06	/************************/
      07	double snx(double x)
      08	{
      09		double y = exp(x) - 3.0 * x;
      10		return y;
      11	}
      12	
      13	/********************/
      14	/* 関数の微分の計算 */
      15	/********************/
      16	double dsnx(double x)
      17	{
      18		double y = exp(x) - 3.0;
      19		return y;
      20	}
      21	
      22	/*****************************************************/
      23	/* Newton法による非線形方程式(f(x)=0)の解            */
      24	/*      fn : f(x)を計算する関数名                    */
      25	/*      dfn : f(x)の微分を計算する関数名             */
      26	/*      x0 : 初期値                                  */
      27	/*      eps1 : 終了条件1(|x(k+1)-x(k)|<eps1)   */
      28	/*      eps2 : 終了条件2(|f(x(k))|<eps2)       */
      29	/*      max : 最大試行回数                           */
      30	/*      ind : 実際の試行回数                         */
      31	/*            (負の時は解を得ることができなかった) */
      32	/*      return : 解                                  */
      33	/*****************************************************/
      34	double func6(double(*fn)(double), double(*dfn)(double), double x0,
      35				  double eps1, double eps2, int max, int *ind)
      36	{
      37		double x = x0, x1 = x0;
      38		int sw = 0;
      39		*ind   = 0;
      40	
      41		while (sw == 0 && *ind >= 0) {
      42			sw    = 1;
      43			*ind += 1;
      44			double g = fn(x1);
      45			if (fabs(g) > eps2) {
      46				if (*ind <= max) {
      47					double dg = dfn(x1);
      48					if (fabs(dg) > eps2) {
      49						x = x1 - g / dg;
      50						if (fabs(x-x1) > eps1 && fabs(x-x1) > eps1*fabs(x)) {
      51							x1 = x;
      52							sw = 0;
      53						}
      54					}
      55					else
      56						*ind = -1;
      57				}
      58				else
      59					*ind = -1;
      60			}
      61		}
      62	
      63		return x;
      64	}
      65	
      66	int main()
      67	{
      68		printf("関数名(Newton 法)\n");
      69		double eps1 = 1.0e-7;
      70		double eps2 = 1.0e-10;
      71		double x0   = 0.0;
      72		int max     = 20;
      73		int ind;
      74		double x = func6(snx, dsnx, x0, eps1, eps2, max, &ind);
      75		printf("   回数=%d  x=%f  関数値=%f  微係数=%f\n", ind, x, snx(x), dsnx(x));
      76	
      77		return 0;
      78	}
      				
        上と同様,関数名を関数の引数とした場合の例です.この例においては,ニュートン法によって非線形方程式 f(x) = ex - 3x = 0 の解を求めています.解を求めるための関数 func6 に,関数値を計算するための関数名( snx ),関数の微分値を計算するための関数名( dsnx ),初期値( x0 ),収束判定のための閾値( eps1,eps2 ),最大試行回数( max ),及び,収束までの実行回数を返す変数( ind )を引数として渡しています.このプログラム内の出力文によって,以下に示すような結果が得られます.
      関数名(Newton 法)
         回数=5  x=0.619061  関数値=0.000000  微係数=-1.142816					

  2. Java

    1. 基本型データ,文字列
      01	import java.io.*;
      02	
      03	public class Test {
      04		/*******************/
      05		/* main プログラム */
      06		/*******************/
      07		public static void main(String args[]) throws IOException
      08		{
      09			Test1 ts = new Test1();
      10		}
      11	}
      12	
      13	class Test1 {
      14		Test1()
      15		{
      16			System.out.printf("基本型,文字列\n");
      17			int a1 = 10, b1 = 20, c1 = 0;
      18			String s1 = "abc", s2 = new String("abc");
      19			System.out.printf("   前 %d %d %d %s %s\n", a1, b1, c1, s1, s2);
      20			c1 = func1(a1, b1, s1, s2);
      21			System.out.printf("   後 %d %d %d %s %s\n", a1, b1, c1, s1, s2);
      22		}
      23	
      24		/**********************************/
      25		/* 2 つの整数の和                 */
      26		/*      u, v : 和を計算するデータ */
      27		/*      t1, t2 : 文字列           */
      28		/*      return : u + v            */
      29		/**********************************/
      30		int func1(int u, int v, String t1, String t2)
      31		{
      32			t1    = t1.replace('a', 'x');
      33			t2    = t2.replace('a', 'x');
      34			u     = 100;
      35			int a = u + v;
      36			return a;
      37		}
      38	}
      				
        基本型データ及び文字列を関数の引数とした場合の例です.加算を行う変数 a1,b1 と s1,s2 を関数 func1 に引数として渡し,変数 c1 に関数の戻り値として結果が代入されています.変数 s1 と s2 は文字列( String クラスのオブジェクト)ですが,その定義方法が異なっています.このプログラム内の出力文によって,以下に示すような結果が得られます.この結果は,関数を呼ぶ前と呼んだ後における変数 a1,b1,c1,s1,及び,s2 の値を示しています.a1,b1 のコピーが引数として関数に渡されるため,34 行目において,変数 u (変数 a1 のコピー)の値を変更していますが,変数 a1 はその影響を受けていません.この点は,文字列に関しても同様です.
      基本型,文字列
         前 10 20 0 abc abc
         後 10 20 120 abc abc					
    2. 1 次元配列
      01	import java.io.*;
      02	import java.util.*;
      03	
      04	public class Test {
      05		/*******************/
      06		/* main プログラム */
      07		/*******************/
      08		public static void main(String args[]) throws IOException
      09		{
      10			Test1 ts = new Test1();
      11		}
      12	}
      13	
      14	class Test1 {
      15		Test1()
      16		{
      17			System.out.printf("1 次元配列\n");
      18			int a2[] = {1, 2, 3, 0};
      19			ArrayList <Integer> b2 = new ArrayList <Integer> ();
      20			for (int i1 = 0; i1 < 3; i1++)
      21				b2.add(new Integer(10 * (i1 + 1)));
      22			b2.add(new Integer(0));
      23			System.out.printf("   前 a2 %d %d %d %d\n", a2[0], a2[1], a2[2], a2[3]);
      24			System.out.printf("      b2 %d %d %d %d\n", b2.get(0), b2.get(1), b2.get(2), b2.get(3));
      25			func2(3, a2, b2);
      26			System.out.printf("   後 a2 %d %d %d %d\n", a2[0], a2[1], a2[2], a2[3]);
      27			System.out.printf("      b2 %d %d %d %d\n", b2.get(0), b2.get(1), b2.get(2), b2.get(3));
      28		}
      29	
      30		/************************/
      31		/* 1 次元配列の要素の和 */
      32		/*      n : 要素数      */
      33		/*      u : 配列        */
      34		/************************/
      35		void func2(int n, int u[], ArrayList <Integer> w)
      36		{
      37			int s = 0;
      38			for (int i1 = 0; i1 < n; i1++) {
      39				u[n] += u[i1];
      40				s    += w.get(i1);
      41			}
      42			w.set(n, s);
      43		}
      44	}
      				
        1 次元配列を関数の引数とした場合の例です.関数に対して,0 以外の値が入っている要素の数( 3 ),1 次元配列( a2 ),及び,ArrayList クラスのオブジェクト( b2 )を引数として渡しています.Java における配列の場合は,記憶領域のアドレスが渡されることと同等ですので,関数内においてその各要素の値を変更可能です.そのため,1 番目から 3 番目までの要素の和を 4 番目の要素に記憶しています.また,ArrayList クラスの場合においても,C++ における vector クラスの場合とは異なり,アドレスが渡されているため,要素の和を 4 番目の要素に記憶しています.このプログラム内の出力文によって,以下に示すような結果が得られます.
      1 次元配列
         前 a2 1 2 3 0
            b2 10 20 30 0
         後 a2 1 2 3 6
            b2 10 20 30 60					
    3. 2 次元配列
      01	import java.io.*;
      02	
      03	public class Test {
      04		/*******************/
      05		/* main プログラム */
      06		/*******************/
      07		public static void main(String args[]) throws IOException
      08		{
      09			Test1 ts = new Test1();
      10		}
      11	}
      12	
      13	class Test1 {
      14		Test1()
      15		{
      16			System.out.printf("2 次元配列\n");
      17			int a3[][] = {{1, 2, 3, 0}, {4, 5, 6, 0}};
      18			System.out.printf("   前 a3 %d %d %d %d\n", a3[0][0], a3[0][1], a3[0][2], a3[0][3]);
      19			System.out.printf("         %d %d %d %d\n", a3[1][0], a3[1][1], a3[1][2], a3[1][3]);
      20			func3(2, 3, a3);
      21			System.out.printf("   後 a3 %d %d %d %d\n", a3[0][0], a3[0][1], a3[0][2], a3[0][3]);
      22			System.out.printf("         %d %d %d %d\n", a3[1][0], a3[1][1], a3[1][2], a3[1][3]);
      23		}
      24	
      25		/****************************/
      26		/* 2 次元配列の要素の和     */
      27		/*      n : 行数            */
      28		/*      m : 列数            */
      29		/*      u : 配列            */
      30		/*      u[i1][m] : 各行の和 */
      31		/****************************/
      32		void func3(int n, int m, int u[][])
      33		{
      34			for (int i1 = 0; i1 < n; i1++) {
      35				for (int i2 = 0; i2 < m; i2++)
      36					u[i1][m] += u[i1][i2];
      37			}
      38		}
      39	}
      				
        2 次元配列を関数の引数とした場合の例です.関数に対して,行の数( 2 ),列の数( 3,0 でない列の数 ),2 次元配列( a3 )を引数とし,各行の最後の要素に,その行の和を代入しています.このプログラム内の出力文によって,以下に示すような結果が得られます.
      2 次元配列
         前 a3 1 2 3 0
               4 5 6 0
         後 a3 1 2 3 6
               4 5 6 15					
    4. クラスのオブジェクト
      01	import java.io.*;
      02	
      03	public class Test {
      04		/*******************/
      05		/* main プログラム */
      06		/*******************/
      07		public static void main(String args[]) throws IOException
      08		{
      09			Test1 ts = new Test1();
      10		}
      11	}
      12	
      13	class Test1 {
      14		Test1()
      15		{
      16			System.out.printf("オブジェクト\n");
      17			Example a4 = new Example(3);
      18			System.out.printf("   前 n %d\n", a4.n);
      19			System.out.printf("      x %d %d %d\n", a4.x[0], a4.x[1], a4.x[2]);
      20			func4(a4);
      21			System.out.printf("   後 n %d\n", a4.n);
      22			System.out.printf("      x %d %d %d\n", a4.x[0], a4.x[1], a4.x[2]);
      23		}
      24	
      25		/**************************/
      26		/* オブジェクトの値変更   */
      27		/*      x1 : オブジェクト */
      28		/**************************/
      29		void func4(Example x1)
      30		{
      31			x1.n    = 4;
      32			x1.x[0] = 4;
      33		}
      34	}
      35	
      36	/******************/
      37	/* クラス Example */
      38	/******************/
      39	class Example {
      40		int n;
      41		int x[];
      42		Example(int n1)
      43		{
      44			n = n1;
      45			x = new int [n];
      46			for (int i1 = 0; i1 < n; i1++)
      47				x[i1] = i1;
      48		}
      49	}
      				
        クラスのオブジェクト(クラスの定義は,39 行目~ 49 行目)を関数の引数とした場合の例です.この例では,クラスのオブジェクト( a4 )だけを引数として渡しています.Java においては,C++ とは異なり,オブジェクトのアドレスが渡される場合と等価になります.従って,関数側で関数を呼んだ側のオブジェクトの値を変更することが可能になります( 31 行目~ 32 行目と下に示す出力結果参照).このプログラム内の出力文によって,以下に示すような結果が得られます.
      オブジェクト
         前 n 3
            x 0 1 2
         後 n 4
            x 4 1 2					
    5. 関数名( sort )
      001	import java.io.*;
      002	
      003	public class Test {
      004		/*******************/
      005		/* main プログラム */
      006		/*******************/
      007		public static void main(String args[]) throws IOException
      008		{
      009			Test1 ts = new Test1();
      010		}
      011	}
      012	
      013	class Test1 {
      014		Test1()
      015		{
      016			System.out.printf("関数名(sort)\n");
      017			int a7[] = {3, 2, 5, 4, 1};
      018			int a8[] = {3, 2, 5, 4, 1};
      019			System.out.printf("   前 %d %d %d %d %d\n", a7[0], a7[1], a7[2], a7[3], a7[4]);
      020			System.out.printf("   前 %d %d %d %d %d\n", a8[0], a8[1], a8[2], a8[3], a8[4]);
      021			Sort st = new Sort(0);   // 昇順
      022			func5(5, a7, st);
      023			st = new Sort(1);   // 降順
      024			func5(5, a8, st);
      025			System.out.printf("   後 %d %d %d %d %d\n", a7[0], a7[1], a7[2], a7[3], a7[4]);
      026			System.out.printf("   後 %d %d %d %d %d\n", a8[0], a8[1], a8[2], a8[3], a8[4]);
      027		}
      028	
      029		/*****************************************************************/
      030		/* バブルソート                                                  */
      031		/*      n : データの数                                           */
      032		/*      data : データ                                            */
      033		/*      compare : 比較を行う関数                                 */
      034		/* バブルソートの手順                                            */
      035		/*     1)配列data[i]にn個のデータが入っているものとする.   */
      036		/*        i=0,1,・・・,n-1                                  */
      037		/*     2)i番目のデータとi+1番目のデータを比較し,もし,     */
      038		/*        data[i+1] < data[i] (昇順の場合)            */
      039		/*      であればそれらのデータを交換する. i=0,1,・・・,n-2  */
      040		/*        →この結果,data[n-1]に最も大きなデータが入る  */
      041		/*              ことになる                                       */
      042		/*     3)次に,n-1個のデータに対し上の処理を繰り返す.      */
      043		/*     4)同様に,n-2,n-3,・・・個のデータに対して同じ処理 */
      044		/*        を繰り返す                                             */
      045		/*****************************************************************/
      046		void func5(int n, int data[], Sort st)
      047		{
      048			int i1, sw = 0;
      049		
      050			if (n > 1) {
      051				for (i1 = 0; i1 < n-1; i1++) {
      052					if (st.compare(data[i1], data[i1+1])) {
      053						sw         = 1;
      054						int x      = data[i1];
      055						data[i1]   = data[i1+1];
      056						data[i1+1] = x;
      057					}
      058				}
      059			}
      060	
      061			if (sw > 0)
      062				func5(n-1, data, st);
      063		}
      064	}
      065	
      066	/***************/
      067	/* クラス Sort */
      068	/***************/
      069	class Sort {
      070	
      071		int sw;   // =0 : 昇順,=1 : 降順
      072	
      073		Sort(int swi)
      074		{
      075			sw = swi;
      076		}
      077	
      078		boolean compare(int a, int b)
      079		{
      080			return (sw ==0) ? ascend(a, b) : descend(a, b);
      081		}
      082	
      083		/************************/
      084		/* データの比較(昇順) */
      085		/* a > bの場合に真    */
      086		/************************/
      087		boolean ascend(int a, int b)
      088		{
      089			boolean tf = false;
      090			if (a > b)
      091				tf = true;
      092			return tf;
      093		}
      094	
      095		/************************/
      096		/* データの比較(降順) */
      097		/* a < bの場合に真      */
      098		/************************/
      099		boolean descend(int a, int b)
      100		{
      101			boolean tf = false;
      102			if (a < b)
      103				tf = true;
      104			return tf;
      105		}
      106	}
      				
        Java には,関数名を関数の引数とするような機能が存在しないため,Sort というクラス( 069 行目~ 106 行目)を定義し,そのオブジェクトを引き数として渡してます.バブルソートを行う関数 func5 に,データの数( 5 ),ソートすべきデータ( a7,a8 ),及び,クラス Sort のオブジェクト( st )を引数として渡しています.このプログラム内の出力文によって,以下に示すような結果が得られます.正しくソートが行われているのが分かると思います.
      関数名(sort)
         前 3 2 5 4 1
         前 3 2 5 4 1
         後 1 2 3 4 5
         後 5 4 3 2 1					
    6. 関数名(ニュートン法)
      01	import java.io.*;
      02	
      03	public class Test {
      04		/*******************/
      05		/* main プログラム */
      06		/*******************/
      07		public static void main(String args[]) throws IOException
      08		{
      09			Test1 ts = new Test1();
      10		}
      11	}
      12	
      13	class Test1 {
      14		Test1()
      15		{
      16			System.out.printf("関数名(Newton 法)\n");
      17			double eps1 = 1.0e-7;
      18			double eps2 = 1.0e-10;
      19			double x0   = 0.0;
      20			int max     = 20;
      21			int ind[]   = new int [1];
      22			Newton nt   = new Newton();
      23			double x = func6(nt, x0, eps1, eps2, max, ind);
      24			System.out.printf("   回数=%d  x=%f  関数値=%f  微係数=%f\n", ind[0], x, nt.fn(0, x), nt.fn(1, x));
      25		}
      26	
      27		/*****************************************************/
      28		/* Newton法による非線形方程式(f(x)=0)の解            */
      29		/*      nt : f(x)及びf(x)の微分を計算する関数        */
      30		/*      x0 : 初期値                                  */
      31		/*      eps1 : 終了条件1(|x(k+1)-x(k)|<eps1)   */
      32		/*      eps2 : 終了条件2(|f(x(k))|<eps2)       */
      33		/*      max : 最大試行回数                           */
      34		/*      ind : 実際の試行回数                         */
      35		/*            (負の時は解を得ることができなかった) */
      36		/*      return : 解                                  */
      37		/*****************************************************/
      38		double func6(Newton nt, double x0, double eps1, double eps2, int max, int ind[])
      39		{
      40			double x = x0, x1 = x0;
      41			int sw = 0;
      42			ind[0] = 0;
      43		
      44			while (sw == 0 && ind[0] >= 0) {
      45				sw      = 1;
      46				ind[0] += 1;
      47				double g = nt.fn(0, x1);
      48				if (Math.abs(g) > eps2) {
      49					if (ind[0] <= max) {
      50						double dg = nt.fn(1, x1);
      51						if (Math.abs(dg) > eps2) {
      52							x = x1 - g / dg;
      53							if (Math.abs(x-x1) > eps1 && Math.abs(x-x1) > eps1*Math.abs(x)) {
      54								x1 = x;
      55								sw = 0;
      56							}
      57						}
      58						else
      59							ind[0] = -1;
      60					}
      61					else
      62						ind[0] = -1;
      63				}
      64			}
      65	
      66			return x;
      67		}
      68	}
      69	
      70	/*****************/
      71	/* クラス Newton */
      72	/*****************/
      73	class Newton {
      74		double fn(int sw, double x)
      75		{
      76			double y;
      77			if (sw == 0)   // 関数値の計算
      78				y = Math.exp(x) - 3.0 * x;
      79			else   // 関数の微分の計算
      80				y = Math.exp(x) - 3.0;
      81			return y;
      82		}
      83	}
      				
        上と同様,関数名を引数とする代わりに,Newton クラス( 73 行目~ 83 行目)のオブジェクトを引数として渡しています.この例においては,ニュートン法によって非線形方程式 f(x) = ex - 3x = 0 の解を求めています.解を求めるための関数 func6 に,Newton クラスのオブジェクト( nt ),初期値( x0 ),収束判定のための閾値( eps1,eps2 ),最大試行回数( max ),及び,収束までの実行回数を返す配列変数( ind )を引数として渡しています.このプログラム内の出力文によって,以下に示すような結果が得られます.
      関数名(Newton 法)
         回数=5  x=0.619061  関数値=-0.000000  微係数=-1.142816					

  3. JavaScript

      ここをクリックすれば,ブラウザ上で以下に示す全てのプログラムを同時に実行することができます.表示された画面の「 OK 」ボタンをクリックすると,実行結果が表示されます.また,ページのソースを表示すれば,下に示した JavaScript のソースプログラムも表示可能です.

    1. 基本型データ,文字列
      01	<!DOCTYPE HTML>
      02	<HTML>
      03	<HEAD>
      04		<TITLE>関数</TITLE>
      05		<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
      06		<SCRIPT TYPE="text/javascript">
      07			function run() {
      08				let str = "基本型,文字列\n";
      09				let a1  = 10, b1 = 20, c1 = 0;
      10				let s1 = "abc", s2 = new String("abc");
      11				str    += "   前 " + a1 + " " + b1 + " " + c1 + " " + s1 + " " + s2 + "\n";
      12				c1 = func1(a1, b1, s1, s2);
      13				str    += "   後 " + a1 + " " + b1 + " " + c1 + " " + s1 + " " + s2 + "\n";
      14					// 結果の設定
      15				document.getElementById("tx").value = str;
      16			}
      17	
      18			/**********************************/
      19			/* 2 つの整数の和                 */
      20			/*      u, v : 和を計算するデータ */
      21			/*      t1, t2 : 文字列           */
      22			/*      return : u + v            */
      23			/**********************************/
      24			function func1(u, v, t1, t2)
      25			{
      26				t1    = t1.replace(/a/, "x");
      27				t2    = t2.replace(/a/, "x");
      28				u     = 100;
      29				let a = u + v;
      30				return a;
      31			}
      32		</SCRIPT>
      33	</HEAD>
      34	<BODY  STYLE="font-size:130%">
      35		<P STYLE="text-align:center">
      36			<INPUT TYPE="button" VALUE="OK" onClick="run()" STYLE="font-size:90%"><BR><BR>
      37			<TEXTAREA TYPE="text" ID="tx" COLS="50" ROWS="10" STYLE="font-size: 100%"></TEXTAREA>
      38		</P>
      39	</BODY>
      40	</HTML>
      				
        基本型データ及び文字列を関数の引数とした場合の例です.加算を行う変数 a1,b1 と s1,s2 を関数 func1 に引数として渡し,変数 c1 に関数の戻り値として結果が代入されています.変数 s1 (文字列定数)と s2 ( String オブジェクト)は文字列ですが,その定義方法が異なっています.このプログラム内の出力文によって,以下に示すような結果が得られます.この結果は,関数を呼ぶ前と呼んだ後における変数 a1,b1,c1,s1,及び,s2 の値を示しています.a1,b1 のコピーが引数として関数に渡されるため,28 行目において,変数 u (変数 a1 のコピー)の値を変更していますが,変数 a1 はその影響を受けていません.文字列に関しても同様です.
      基本型,文字列
         前 10 20 0 abc abc
         後 10 20 120 abc abc					
    2. 1 次元配列
      01	<!DOCTYPE HTML>
      02	<HTML>
      03	<HEAD>
      04		<TITLE>関数</TITLE>
      05		<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
      06		<SCRIPT TYPE="text/javascript">
      07			function run() {
      08				let str = "1 次元配列\n";
      09				let a2  = new Array(1, 2, 3, 0);
      10				str    += "   前 " + a2[0] + " " + a2[1] + " " + a2[2] + " " + a2[3] + "\n";
      11				func2(3, a2);
      12				str += "   後 " + a2[0] + " " + a2[1] + " " + a2[2] + " " + a2[3] + "\n";
      13					// 結果の設定
      14				document.getElementById("tx").value = str;
      15			}
      16	
      17			/************************/
      18			/* 1 次元配列の要素の和 */
      19			/*      n : 要素数      */
      20			/*      u : 配列        */
      21			/************************/
      22			function func2(n, u)
      23			{
      24				for (let i1 = 0; i1 < n; i1++)
      25					u[n] += u[i1];
      26			}
      27		</SCRIPT>
      28	</HEAD>
      29	<BODY  STYLE="font-size:130%">
      30		<P STYLE="text-align:center">
      31			<INPUT TYPE="button" VALUE="OK" onClick="run()" STYLE="font-size:90%"><BR><BR>
      32			<TEXTAREA TYPE="text" ID="tx" COLS="50" ROWS="10" STYLE="font-size: 100%"></TEXTAREA>
      33		</P>
      34	</BODY>
      35	</HTML>
      				
        1 次元配列を関数の引数とした場合の例です.関数に対して,0 以外の値が入っている要素の数( 3 ),及び,1 次元配列( a2 )を引数として渡しています.JavaScript における配列の場合は,記憶領域のアドレスが渡されることと同等ですので,関数内においてその各要素の値を変更可能です.そのため,1 番目から 3 番目までの要素の和を 4 番目の要素に記憶しています.このプログラム内の出力文によって,以下に示すような結果が得られます.
      1 次元配列
         前 1 2 3 0
         後 1 2 3 6					
    3. 2 次元配列
      01	<!DOCTYPE HTML>
      02	<HTML>
      03	<HEAD>
      04		<TITLE>関数</TITLE>
      05		<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
      06		<SCRIPT TYPE="text/javascript">
      07			function run() {
      08				str    = "2 次元配列\n";
      09				let a3 = new Array(2);
      10				a3[0] = new Array(1, 2, 3, 0);
      11				a3[1] = new Array(4, 5, 6, 0);
      12				str += "   前 " + a3[0][0] + " " + a3[0][1] + " " + a3[0][2] + " " + a3[0][3] + "\n";
      13				str += "      " + a3[1][0] + " " + a3[1][1] + " " + a3[1][2] + " " + a3[1][3] + "\n";
      14				func3(2, 3, a3);
      15				str += "   後 " + a3[0][0] + " " + a3[0][1] + " " + a3[0][2] + " " + a3[0][3] + "\n";
      16				str += "      " + a3[1][0] + " " + a3[1][1] + " " + a3[1][2] + " " + a3[1][3] + "\n";
      17					// 結果の設定
      18				document.getElementById("tx").value = str;
      19			}
      20	
      21			/************************/
      22			/* 2 次元配列の要素の和 */
      23			/*      n : 行数        */
      24			/*      m : 列数        */
      25			/*      u : 配列        */
      26			/************************/
      27			function func3(n, m, u)
      28			{
      29				for (let i1 = 0; i1 < n; i1++) {
      30					for (let i2 = 0; i2 < m; i2++)
      31						u[i1][m] += u[i1][i2];
      32				}
      33			}
      34		</SCRIPT>
      35	</HEAD>
      36	<BODY  STYLE="font-size:130%">
      37		<P STYLE="text-align:center">
      38			<INPUT TYPE="button" VALUE="OK" onClick="run()" STYLE="font-size:90%"><BR><BR>
      39			<TEXTAREA TYPE="text" ID="tx" COLS="50" ROWS="10" STYLE="font-size: 100%"></TEXTAREA>
      40		</P>
      41	</BODY>
      42	</HTML>
      				
        2 次元配列を関数の引数とした場合の例です.関数に対して,行の数( 2 ),列の数( 3,0 でない列の数 ),2 次元配列( a3 )を引数とし,各行の最後の列にその列の要素の和を代入しています.このプログラム内の出力文によって,以下に示すような結果が得られます.
      2 次元配列
         前 1 2 3 0
            4 5 6 0
         後 1 2 3 6
            4 5 6 15					
    4. クラスとオブジェクト
      01	<!DOCTYPE HTML>
      02	<HTML>
      03	<HEAD>
      04		<TITLE>関数</TITLE>
      05		<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
      06		<SCRIPT TYPE="text/javascript">
      07			function run() {
      08				let str = "オブジェクト\n";
      09				let a4  = new Example();
      10				str    += "   前 x " + a4.x + " y " + a4.y[0] + " " + a4.y[1] + " " + a4.y[2] + "\n";
      11				func4(a4);
      12				str   += "   後 x " + a4.x + " y " + a4.y[0] + " " + a4.y[1] + " " + a4.y[2] + "\n";
      13					// 結果の設定
      14				document.getElementById("tx").value = str;
      15			}
      16	
      17			/************************/
      18			/* オブジェクト Example */
      19			/************************/
      20			function Example()
      21			{
      22				this.x = 1;
      23				this.y = new Array(10, 20, 30);
      24			}
      25	
      26			/*************************/
      27			/* オブジェクトの値変更  */
      28			/*      a : オブジェクト */
      29			/*************************/
      30			function func4(a)
      31			{
      32				a.x    = 2;
      33				a.y[0] = 40;
      34			}
      35		</SCRIPT>
      36	</HEAD>
      37	<BODY  STYLE="font-size:130%">
      38		<P STYLE="text-align:center">
      39			<INPUT TYPE="button" VALUE="OK" onClick="run()" STYLE="font-size:90%"><BR><BR>
      40			<TEXTAREA TYPE="text" ID="tx" COLS="50" ROWS="10" STYLE="font-size: 100%"></TEXTAREA>
      41		</P>
      42	</BODY>
      43	</HTML>
      				
        クラスと似た概念であるオブジェクト(オブジェクトの定義は,20 行目~ 24 行目)を関数の引数とした場合の例です(クラスを使用しても同様).この例では,オブジェクト( a4 )だけを引数として渡しています.JavaScript においては,C++ とは異なり,オブジェクトのアドレスが渡される場合と等価になります.従って,関数側で関数を呼んだ側のオブジェクトの値を変更することが可能になります( 32 行目~ 33 行目と下に示す出力結果参照).このプログラム内の出力文によって,以下に示すような結果が得られます.
      オブジェクト
         前 x 1 y 10 20 30
         後 x 2 y 40 20 30					
    5. 関数名( sort )
      01	<!DOCTYPE HTML>
      02	<HTML>
      03	<HEAD>
      04		<TITLE>関数</TITLE>
      05		<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
      06		<SCRIPT TYPE="text/javascript">
      07			function run() {
      08				let str = "関数名(sort)\n";
      09				let a7  = new Array(3, 2, 5, 4, 1);
      10				let a8  = new Array(3, 2, 5, 4, 1);
      11				str    += "   前 " + a7[0] + " " + a7[1] + " " + a7[2] + " " + a7[3] + " " + a7[4] + "\n";
      12				str    += "   前 " + a8[0] + " " + a8[1] + " " + a8[2] + " " + a8[3] + " " + a8[4] + "\n";
      13				func5(5, a7, ascend);   // 昇順
      14				func5(5, a8, descend);   // 降順
      15				str += "   後 " + a7[0] + " " + a7[1] + " " + a7[2] + " " + a7[3] + " " + a7[4] + "\n";
      16				str += "   後 " + a8[0] + " " + a8[1] + " " + a8[2] + " " + a8[3] + " " + a8[4] + "\n";
      17					// 結果の設定
      18				document.getElementById("tx").value = str;
      19			}
      20	
      21			/*****************************/
      22			/* データの比較(昇順)      */
      23			/* a > bの場合に0以外(真) */
      24			/*****************************/
      25			function ascend(a, b)
      26			{
      27				return a > b;
      28			}
      29	
      30			/*****************************/
      31			/* データの比較(降順)      */
      32			/* a < bの場合に0以外(真) */
      33			/*****************************/
      34			function descend(a, b)
      35			{
      36				return a < b;
      37			}
      38			
      39			/*****************************************************************/
      40			/* バブルソート                                                  */
      41			/*      n : データの数                                           */
      42			/*      data : データ                                            */
      43			/*      compare : 比較を行う関数                                 */
      44			/* バブルソートの手順                                            */
      45			/*     1)配列data[i]にn個のデータが入っているものとする.   */
      46			/*        i=0,1,・・・,n-1                                  */
      47			/*     2)i番目のデータとi+1番目のデータを比較し,もし,     */
      48			/*        data[i+1] < data[i] (昇順の場合)            */
      49			/*      であればそれらのデータを交換する. i=0,1,・・・,n-2  */
      50			/*        →この結果,data[n-1]に最も大きなデータが入る  */
      51			/*              ことになる                                       */
      52			/*     3)次に,n-1個のデータに対し上の処理を繰り返す.      */
      53			/*     4)同様に,n-2,n-3,・・・個のデータに対して同じ処理 */
      54			/*        を繰り返す                                             */
      55			/*****************************************************************/
      56			function func5(n, data, compare)
      57			{
      58				let sw = 0;
      59			
      60				if (n > 1) {
      61					for (let i1 = 0; i1 < n-1; i1++) {
      62						if (compare(data[i1], data[i1+1])) {
      63							sw         = 1;
      64							let x      = data[i1];
      65							data[i1]   = data[i1+1];
      66							data[i1+1] = x;
      67						}
      68					}
      69				}
      70			
      71				if (sw > 0)
      72					func5(n-1, data, compare);
      73			}
      74		</SCRIPT>
      75	</HEAD>
      76	<BODY  STYLE="font-size:130%">
      77		<P STYLE="text-align:center">
      78			<INPUT TYPE="button" VALUE="OK" onClick="run()" STYLE="font-size:90%"><BR><BR>
      79			<TEXTAREA TYPE="text" ID="tx" COLS="50" ROWS="10" STYLE="font-size: 100%"></TEXTAREA>
      80		</P>
      81	</BODY>
      82	</HTML>
      				
        関数名を関数の引数とした場合の例です.バブルソートを行う関数 func5 に,データの数( 5 ),ソートすべきデータ( a7,a8 ),及び,比較を実行するための関数名( ascend,descend )を引数として渡しています.このプログラム内の出力文によって,以下に示すような結果が得られます.正しくソートが行われているのが分かると思います.
      関数名(sort)
         前 3 2 5 4 1
         前 3 2 5 4 1
         後 1 2 3 4 5
         後 5 4 3 2 1					
    6. 関数名(ニュートン法)
      01	<!DOCTYPE HTML>
      02	<HTML>
      03	<HEAD>
      04		<TITLE>関数</TITLE>
      05		<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
      06		<SCRIPT TYPE="text/javascript">
      07			function run() {
      08				let str  = "関数名(Newton 法)\n";
      09				let eps1 = 1.0e-7;
      10				let eps2 = 1.0e-10;
      11				let x0   = 0.0;
      12				let max  = 20;
      13				let ind  = new Array(1);
      14				let x    = func6(snx, dsnx, x0, eps1, eps2, max, ind);
      15				str     += "   回数=" + ind[0] + "  x=" + x + "  関数値=" + snx(x) + "  微係数=" + dsnx(x) + "\n";
      16					// 結果の設定
      17				document.getElementById("tx").value = str;
      18			}
      19	
      20			/************************/
      21			/* 関数値(f(x))の計算 */
      22			/************************/
      23			function snx(x)
      24			{
      25				let y = Math.exp(x) - 3.0 * x;
      26				return y;
      27			}
      28			
      29			/********************/
      30			/* 関数の微分の計算 */
      31			/********************/
      32			function dsnx(x)
      33			{
      34				let y = Math.exp(x) - 3.0;
      35				return y;
      36			}
      37			
      38			/*****************************************************/
      39			/* Newton法による非線形方程式(f(x)=0)の解            */
      40			/*      fn : f(x)を計算する関数名                    */
      41			/*      dfn : f(x)の微分を計算する関数名             */
      42			/*      x0 : 初期値                                  */
      43			/*      eps1 : 終了条件1(|x(k+1)-x(k)|<eps1)   */
      44			/*      eps2 : 終了条件2(|f(x(k))|<eps2)       */
      45			/*      max : 最大試行回数                           */
      46			/*      ind : 実際の試行回数                         */
      47			/*            (負の時は解を得ることができなかった) */
      48			/*      return : 解                                  */
      49			/*****************************************************/
      50			function func6(f, df, x0, eps1, eps2, max, ind)
      51			{
      52				let x = x0, x1 = x0, sw = 0;
      53				ind[0] = 0;
      54			
      55				while (sw == 0 && ind[0] >= 0) {
      56					sw      = 1;
      57					ind[0] += 1;
      58					let g   = f(x1);
      59					if (Math.abs(g) > eps2) {
      60						if (ind[0] <= max) {
      61							let dg = df(x1);
      62							if (Math.abs(dg) > eps2) {
      63								x = x1 - g / dg;
      64								if (Math.abs(x-x1) > eps1 && Math.abs(x-x1) > eps1*Math.abs(x)) {
      65									x1 = x;
      66									sw = 0;
      67								}
      68							}
      69							else
      70								ind[0] = -1;
      71						}
      72						else
      73							ind[0] = -1;
      74					}
      75				}
      76			
      77				return x;
      78			}
      79		</SCRIPT>
      80	</HEAD>
      81	<BODY  STYLE="font-size:130%">
      82		<P STYLE="text-align:center">
      83			<INPUT TYPE="button" VALUE="OK" onClick="run()" STYLE="font-size:90%"><BR><BR>
      84			<TEXTAREA TYPE="text" ID="tx" COLS="50" ROWS="10" STYLE="font-size: 100%"></TEXTAREA>
      85		</P>
      86	</BODY>
      87	</HTML>
      				
        上と同様,関数名を関数の引数とした場合の例です.この例においては,ニュートン法によって非線形方程式 f(x) = ex - 3x = 0 の解を求めています.解を求めるための関数 func6 に,関数値を計算するための関数名( snx ),関数の微分値を計算するための関数名( dsnx ),初期値( x0 ),収束判定のための閾値( eps1,eps2 ),最大試行回数( max ),及び,収束までの実行回数を返す配列変数( ind )を引数として渡しています.このプログラム内の出力文によって,以下に示すような結果が得られます.
      関数名(Newton 法)
         回数=5  x=0.6190612867359452  関数値=-2.220446049250313e-16  微係数=-1.1428161397921645					

  4. PHP

    1. 基本型データ,文字列
      01	<?php
      02		printf("基本型,文字列\n");
      03		$a1 = 10;
      04		$b1 = 20;
      05		$c1 = 0;
      06		$d1 = 0;
      07		$s1 = "abc";
      08		printf("   前 %d %d %d %d %s\n", $a1, $b1, $c1, $d1, $s1);
      09		$c1 = func1($a1, $b1, $d1, $s1);
      10		printf("   後 %d %d %d %d %s\n", $a1, $b1, $c1, $d1, $s1);
      11	
      12		/************************************/
      13		/* 2 つの整数の和                   */
      14		/*      $u, $v : 和を計算するデータ */
      15		/*      $w : $u + $v                */
      16		/*      $t1 : 文字列                */
      17		/*      return : $u + $v            */
      18		/************************************/
      19		function func1($u, $v, &$w, $t1)
      20		{
      21			$t1 = str_replace("a", "x", $t1);
      22			$u  = 100;
      23			$a  = $u + $v;
      24			$w  = $a;
      25			return $a;
      26		}
      27	?>
      				
        基本型データ及び文字列を関数の引数とした場合の例です.09 行目と 19 行目から明らかなように,変数 $d1 に関しては参照渡しをしており,変数 $c1 には,関数の戻り値が代入されます.また,変数 $s1 は文字列です.このプログラム内の出力文によって,以下に示すような結果が得られます.この結果は,関数を呼ぶ前と呼んだ後における変数 $a1,$b1,$c1,$d1,及び,$s1 の値を示しています.
      基本型,文字列
         前 10 20 0 0 abc
         後 10 20 120 120 abc					
        22 行目において,変数 $u (変数 $a1 のコピー)の値を変更していますが,変数 $a1 はその影響を受けていません.文字列に関しても同様です.しかし,参照渡しをした変数 $d1 は,24 行目の処理によって,その値が変化しています.当然,25 行目の return 文による戻り値を代入した変数 $c1 の値も変化します.
    2. 1 次元配列
      01	<?php
      02		printf("1 次元配列\n");
      03		$a2 = array(1, 2, 3, 0);
      04		$b2 = $a2;   // $b2 は,$a2 と異なる配列となる
      05		printf("   前 a2 %d %d %d %d\n", $a2[0], $a2[1], $a2[2], $a2[3]);
      06		printf("      b2 %d %d %d %d\n", $b2[0], $b2[1], $b2[2], $b2[3]);
      07		$x = func2(3, $a2, $b2);
      08		printf("   後 a2 %d %d %d %d %d\n", $a2[0], $a2[1], $a2[2], $a2[3], $x);
      09		printf("      b2 %d %d %d %d\n", $b2[0], $b2[1], $b2[2], $b2[3]);
      10	
      11		/************************/
      12		/* 1 次元配列の要素の和 */
      13		/*      $n : 要素数     */
      14		/*      $u,$w : 配列    */
      15		/*      return : 和     */
      16		/************************/
      17		function func2($n, $u, &$w)
      18		{
      19			for ($i1 = 0; $i1 < $n; $i1++) {
      20				$u[$n] += $u[$i1];
      21				$w[$n] += $w[$i1];
      22			}
      23			return $u[$n];
      24		}
      25	?>
      				
        1 次元配列を関数の引数とした場合の例です.関数に対して,0 以外の値が入っている要素の数( 3 ),及び,1 次元配列( $a2,$b2,$b2 は参照渡し )を引数として渡し,関数の戻り値は変数 $x に代入しています.関数内において,1 番目から 3 番目までの要素の和を 4 番目の要素に記憶しています.しかし,下に示す出力結果からも明らかなように,関数を呼んだ側における $a2 の 4 番目の要素の値は変化しません.そのため,結果は関数の戻り値として返しています.しかし,参照渡しを行った $b2 に関しては,その値が変化しています.このように,PHP においては,他の言語とは異なり,参照渡しを行わない限り,配列であってもその内容がすべてコピーされて関数に引き渡され,関数内で行った値の変更が,関数を呼んだ側に反映されませんのでので注意してください.このプログラム内の出力文によって,以下に示すような結果が得られます.
      1 次元配列
         前 a2 1 2 3 0
            b2 1 2 3 0
         後 a2 1 2 3 0 6
            b2 1 2 3 6					
    3. 2 次元配列
      01	<?php
      02		printf("2 次元配列\n");
      03		$a3 = array(2);
      04		$a3[0] = array(1, 2, 3, 0);
      05		$a3[1] = array(4, 5, 6, 0);
      06		printf("   前 %d %d %d %d\n", $a3[0][0], $a3[0][1], $a3[0][2], $a3[0][3]);
      07		printf("      %d %d %d %d\n", $a3[1][0], $a3[1][1], $a3[1][2], $a3[1][3]);
      08		$c3 = func3(2, 3, $a3);
      09		printf("   後 %d %d %d %d\n", $a3[0][0], $a3[0][1], $a3[0][2], $a3[0][3]);
      10		printf("      %d %d %d %d\n", $a3[1][0], $a3[1][1], $a3[1][2], $a3[1][3]);
      11	
      12		/************************/
      13		/* 2 次元配列の要素の和 */
      14		/*      $n : 行数       */
      15		/*      $m : 列数       */
      16		/*      $u : 配列       */
      17		/************************/
      18		function func3($n, $m, &$u)
      19		{
      20			for ($i1 = 0; $i1 < $n; $i1++) {
      21				for ($i2 = 0; $i2 < $m; $i2++)
      22					$u[$i1][$m] += $u[$i1][$i2];
      23			}
      24		}
      25	?>
      				
        2 次元配列を関数の引数とした場合の例です.関数に対して,行の数( 2 ),列の数( 3,0 でない列の数 ),2 次元配列( $a3 )を引数として渡しています.なお,$a3 に対しては,参照渡しを行い,各行の最後の要素に,その行の要素の和が代入されます.2 次元配列の場合においても,参照渡しを行わない限り,関数内において,関数を呼んだ側における配列の値を変更できません.このプログラム内の出力文によって,以下に示すような結果が得られます.
      2 次元配列
         前 1 2 3 0
            4 5 6 0
         後 1 2 3 6
            4 5 6 15					
    4. クラスのオブジェクト
      01	<?php
      02		printf("オブジェクト\n");
      03		$a4 = new Example(1);
      04		$a5 = new Example(1);
      05		printf("   前 a4 n %d\n", $a4->n);
      06		printf("      x %d %d %d\n", $a4->x[0], $a4->x[1], $a4->x[2]);
      07		printf("   前 a5 n %d\n", $a5->n);
      08		printf("      x %d %d %d\n", $a5->x[0], $a5->x[1], $a5->x[2]);
      09		func4($a4, $a5);
      10		printf("   後 a4 n %d\n", $a4->n);
      11		printf("      x %d %d %d\n", $a4->x[0], $a4->x[1], $a4->x[2]);
      12		printf("   後 a5 n %d\n", $a5->n);
      13		printf("      x %d %d %d\n", $a5->x[0], $a5->x[1], $a5->x[2]);
      14	
      15		/******************/
      16		/* クラス Example */
      17		/******************/
      18		class Example {
      19			public $n;
      20			public $x;
      21			function Example($n)
      22			{
      23				$this->n = $n;
      24				$this->x = array(1, 2, 3);
      25			}
      26		}
      27	
      28		/************************/
      29		/* オブジェクトの値変更 */
      30		/*      x1 : コピー     */
      31		/*      x2 : 参照       */
      32		/************************/
      33		function func4($x1, &$x2)
      34		{
      35			$x1->n = 2;
      36			$x2->n = 3;
      37			$x1->x[0] = 4;
      38			$x2->x[0] = 5;
      39		}
      40	?>
      				
        クラスのオブジェクト(クラスの定義は,18 行目~ 26 行目)を関数の引数とした場合の例です.関数に対して,クラスのオブジェクト( $a4,$a5,$a5 は参照渡し)を引数として渡しています.クラスのオブジェクトの場合は,配列とは異なり,そのアドレスが渡された場合と同等になります.従って,参照渡しを行わなくても,関数側で関数を呼んだ側のオブジェクトの値を変更することが可能になります.このプログラム内の出力文によって,以下に示すような結果が得られます.
      オブジェクト
         前 a4 n 1
            x 1 2 3
         前 a5 n 1
            x 1 2 3
         後 a4 n 2
            x 4 2 3
         後 a5 n 3
            x 5 2 3					
    5. 関数名( sort )
      01	<?php
      02		printf("関数名(sort)\n");
      03		$a7 = array(3, 2, 5, 4, 1);
      04		$a8 = array(3, 2, 5, 4, 1);
      05		printf("   前 %d %d %d %d %d\n", $a7[0], $a7[1], $a7[2], $a7[3], $a7[4]);
      06		printf("   前 %d %d %d %d %d\n", $a8[0], $a8[1], $a8[2], $a8[3], $a8[4]);
      07		func5(5, $a7, "ascend");   // 昇順
      08		func5(5, $a8, "descend");   // 降順
      09		printf("   後 %d %d %d %d %d\n", $a7[0], $a7[1], $a7[2], $a7[3], $a7[4]);
      10		printf("   後 %d %d %d %d %d\n", $a8[0], $a8[1], $a8[2], $a8[3], $a8[4]);
      11	
      12		/*****************************/
      13		/* データの比較(昇順)      */
      14		/* a > bの場合に0以外(真) */
      15		/*****************************/
      16		function ascend($a, $b)
      17		{
      18			return $a > $b;
      19		}
      20		
      21		/*****************************/
      22		/* データの比較(降順)      */
      23		/* a < bの場合に0以外(真) */
      24		/*****************************/
      25		function descend($a, $b)
      26		{
      27			return $a < $b;
      28		}
      29		
      30		/*****************************************************************/
      31		/* バブルソート                                                  */
      32		/*      n : データの数                                           */
      33		/*      data : データ                                            */
      34		/*      compare : 比較を行う関数                                 */
      35		/* バブルソートの手順                                            */
      36		/*     1)配列data[i]にn個のデータが入っているものとする.   */
      37		/*        i=0,1,・・・,n-1                                  */
      38		/*     2)i番目のデータとi+1番目のデータを比較し,もし,     */
      39		/*        data[i+1] < data[i] (昇順の場合)            */
      40		/*      であればそれらのデータを交換する. i=0,1,・・・,n-2  */
      41		/*        →この結果,data[n-1]に最も大きなデータが入る  */
      42		/*              ことになる                                       */
      43		/*     3)次に,n-1個のデータに対し上の処理を繰り返す.      */
      44		/*     4)同様に,n-2,n-3,・・・個のデータに対して同じ処理 */
      45		/*        を繰り返す                                             */
      46		/*****************************************************************/
      47		function func5($n, &$data, $compare)
      48		{
      49			$sw = 0;
      50		
      51			if ($n > 1) {
      52				for ($i1 = 0; $i1 < $n-1; $i1++) {
      53					if ($compare($data[$i1], $data[$i1+1])) {
      54						$sw          = 1;
      55						$x           = $data[$i1];
      56						$data[$i1]   = $data[$i1+1];
      57						$data[$i1+1] = $x;
      58					}
      59				}
      60			}
      61		
      62			if ($sw > 0)
      63				func5($n-1, $data, $compare);
      64		}
      65	?>
      				
        関数名を関数の引数とした場合の例です.ただし,PHP にはその機能がありませんので,文字列として関数名を送っています.バブルソートを行う関数 func5 に,データの数( 5 ),ソートすべきデータ( $a7,$a8 ),及び,比較を実行するための関数名( "ascend","descend" )を引数として渡しています.このプログラム内の出力文によって,以下に示すような結果が得られます.正しくソートが行われているのが分かると思います.
      関数名(sort)
         前 3 2 5 4 1
         前 3 2 5 4 1
         後 1 2 3 4 5
         後 5 4 3 2 1					
    6. 関数名(ニュートン法)
      01	<?php
      02		printf("関数名(Newton 法)\n");
      03		$eps1 = 1.0e-7;
      04		$eps2 = 1.0e-10;
      05		$x0   = 0.0;
      06		$max  = 20;
      07		$ind  = 0;
      08		$x = func6("snx", "dsnx", $x0, $eps1, $eps2, $max, $ind);
      09		printf("   回数=%d  x=%f  関数値=%f  微係数=%f\n", $ind, $x, snx($x), dsnx($x));
      10	
      11		/************************/
      12		/* 関数値(f(x))の計算 */
      13		/************************/
      14		function snx($x)
      15		{
      16			$y = exp($x) - 3.0 * $x;
      17			return $y;
      18		}
      19		
      20		/********************/
      21		/* 関数の微分の計算 */
      22		/********************/
      23		function dsnx($x)
      24		{
      25			$y = exp($x) - 3.0;
      26			return $y;
      27		}
      28		
      29		/*****************************************************/
      30		/* Newton法による非線形方程式(f(x)=0)の解            */
      31		/*      fn : f(x)を計算する関数名                    */
      32		/*      dfn : f(x)の微分を計算する関数名             */
      33		/*      x0 : 初期値                                  */
      34		/*      eps1 : 終了条件1(|x(k+1)-x(k)|<eps1)   */
      35		/*      eps2 : 終了条件2(|f(x(k))|<eps2)       */
      36		/*      max : 最大試行回数                           */
      37		/*      ind : 実際の試行回数                         */
      38		/*            (負の時は解を得ることができなかった) */
      39		/*      return : 解                                  */
      40		/*****************************************************/
      41		function func6($f, $df, $x0, $eps1, $eps2, $max, &$ind)
      42		{
      43			$x   = $x0;
      44			$x1  = $x0;
      45			$sw  = 0;
      46			$ind = 0;
      47		
      48			while ($sw == 0 && $ind >= 0) {
      49				$sw   = 1;
      50				$ind += 1;
      51				$g    = $f($x1);
      52				if (abs($g) > $eps2) {
      53					if ($ind <= $max) {
      54						$dg = $df($x1);
      55						if (abs($dg) > $eps2) {
      56							$x = $x1 - $g / $dg;
      57							if (abs($x-$x1) > $eps1 && abs($x-$x1) > $eps1*abs($x)) {
      58								$x1 = $x;
      59								$sw = 0;
      60							}
      61						}
      62						else
      63							$ind = -1;
      64					}
      65					else
      66						$ind = -1;
      67				}
      68			}
      69		
      70			return $x;
      71		}
      72	?>
      				
        上と同様,関数名を関数の引数とした場合の例です.この例においては,ニュートン法によって非線形方程式 f(x) = ex - 3x = 0 の解を求めています.解を求めるための関数 func6 に,関数値を計算するための関数名( "snx" ),関数の微分値を計算するための関数名( "dsnx" ),初期値( $x0 ),収束判定のための閾値( $eps1,$eps2 ),最大試行回数( $max ),及び,収束までの実行回数を返す変数( $ind,参照渡し)を引数として渡しています.このプログラム内の出力文によって,以下に示すような結果が得られます.
      関数名(Newton 法)
         回数=5  x=0.619061  関数値=-0.000000  微係数=-1.142816					

  5. Ruby

    1. 基本型データ,文字列
      01	##################################
      02	# 2 つの整数の和                 #
      03	#      u, v : 和を計算するデータ #
      04	#      t1, t2, t3, t4 : 文字列   #
      05	#      return : u + v            #
      06	##################################
      07	def func1(u, v, t1, t2, t3, t4)
      08		t1[0..0] = "x";
      09		t2[0..0] = "x";
      10		t3       = "ybc";
      11		t4       = "ybc";
      12		u        = 100;
      13		a        = u + v;
      14		return a;
      15	end
      16	
      17	printf("基本型,文字列\n");
      18	a1 = 10;
      19	b1 = 20;
      20	c1 = 0;
      21	s1 = "abc";
      22	s2 = String.new("abc");
      23	s3 = "abc";
      25	s4 = String.new("abc");
      26	printf("   前 %d %d %d %s %s %s %s\n", a1, b1, c1, s1, s2, s3, s4);
      27	c1 = func1(a1, b1, s1, s2, s3, s4);
      28	printf("   前 %d %d %d %s %s %s %s\n", a1, b1, c1, s1, s2, s3, s4);
      				
        基本型データ及び文字列を関数の引数とした場合の例です.加算を行う変数 a1,b1 と s1,s2,s3,s4 を関数 func1 に引数として渡し,変数 c1 に関数の戻り値として結果が代入されています.変数 s1,s2,s3,s4 は文字列( String クラスのオブジェクト)ですが,その定義方法が異なっています.このプログラム内の出力文によって,以下に示すような結果が得られます.この結果は,関数を呼ぶ前と呼んだ後における変数 a1,b1,c1,s1,及び,s2 の値を示しています.a1,b1 のコピーが引数として関数に渡されるため,10 行目において,変数 u (変数 a1 のコピー)の値を変更していますが,変数 a1 はその影響を受けていません.

        しかし,文字列 s1,s2 の場合は,関数 func1 内における変更( 08 行目,09 行目)によって,s1,s2 の値も変化します.つまり,s1,s2 のアドレス(のコピー)が関数 func1 に渡されたような結果になります.同じ文字列であっても,10 行目,11 行目のような修正を行った場合は,その変更が変数 s3,s4 には反映されません.
      基本型,文字列
         前 10 20 0 abc abc abc abc
         前 10 20 120 xbc xbc abc abc					
    2. 1 次元配列
      01	########################
      02	# 1 次元配列の要素の和 #
      03	#      n : 要素数      #
      04	#      u, v : 配列     #
      05	########################
      06	def func2(n, u)
      07		for i1 in 0 ... n
      08			u[n] += u[i1];
      09		end
      10	end
      11	
      12	printf("1 次元配列\n");
      13	a2 = [1, 2, 3, 0];   # a2 = Array[1, 2, 3, 0]; でも可
      14	printf("   前 %d %d %d %d\n", a2[0], a2[1], a2[2], a2[3]);
      15	func2(3, a2);
      16	printf("   後 %d %d %d %d\n", a2[0], a2[1], a2[2], a2[3]);
      				
        1 次元配列を関数の引数とした場合の例です.関数に対して,0 以外の値が入っている要素の数( 3 ),及び,1 次元配列( a2 )を引数として渡しています.Ruby における配列の場合は,記憶領域のアドレスが渡されることと同等ですので,関数内においてその各要素の値を変更可能です.そのため,1 番目から 3 番目までの要素の和を 4 番目の要素に記憶しています.このプログラム内の出力文によって,以下に示すような結果が得られます.
      1 次元配列
         前 1 2 3 0
         後 1 2 3 6					
    3. 2 次元配列
      01	########################
      02	# 2 次元配列の要素の和 #
      03	#      n : 行数        #
      04	#      m : 列数        #
      05	#      u : 配列        #
      06	########################
      07	def func3(n, m, u)
      08		for i1 in 0 ... n
      09			for i2 in 0 ... m
      10				u[i1][m] += u[i1][i2];
      11			end
      12		end
      13	end
      14	
      15	printf("2 次元配列\n");
      16	a3 = Array[[1, 2, 3, 0], [4, 5, 6, 0]];
      17	printf("   前 %d %d %d %d\n", a3[0][0], a3[0][1], a3[0][2], a3[0][3]);
      18	printf("      %d %d %d %d\n", a3[1][0], a3[1][1], a3[1][2], a3[1][3]);
      19	func3(2, 3, a3);
      20	printf("   後 %d %d %d %d\n", a3[0][0], a3[0][1], a3[0][2], a3[0][3]);
      21	printf("      %d %d %d %d\n", a3[1][0], a3[1][1], a3[1][2], a3[1][3]);
      				
        2 次元配列を関数の引数とした場合の例です.関数に対して,行の数( 2 ),列の数( 3,0 でない列の数 ),2 次元配列( a3 )を引数としています.Ruby においては,基本型変数のアドレスを渡す方法や参照渡しといった方法を利用できないため,各行の最後の要素に,その行に含まれる要素の和を代入しています.このプログラム内の出力文によって,以下に示すような結果が得られます.
      2 次元配列
         前 1 2 3 0
            4 5 6 0
         後 1 2 3 6
            4 5 6 15					
    4. クラスのオブジェクト
      01	##################
      02	# クラス Example #
      03	##################
      04	class Example
      05		def initialize(n)
      06			@_n = n;
      07			@_x = [1, 2, 3];
      08		end
      09		attr_accessor("_n", "_x");
      10	end
      11	
      12	########################
      13	# オブジェクトの値変更 #
      14	#      x1 : コピー     #
      15	########################
      16	def func4(x1)
      17		x1._n    = 4;
      18		x1._x[0] = 5;
      19	end
      20	
      21	printf("オブジェクト\n");
      22	a4 = Example.new(1);
      23	printf("   前 n %d\n", a4._n);
      24	printf("      x %d %d %d\n", a4._x[0], a4._x[1], a4._x[2]);
      25	func4(a4);
      26	printf("   後 n %d\n", a4._n);
      27	printf("      x %d %d %d\n", a4._x[0], a4._x[1], a4._x[2]);
      				
        クラスのオブジェクト(クラスの定義は,04 行目~ 10 行目)を関数の引数とした場合の例です.この例では,オブジェクト( a4 )だけを引数として渡しています.Ruby においては,C++ とは異なり,オブジェクトのアドレスが渡される場合と等価になります.従って,関数側で関数を呼んだ側のオブジェクトの値を変更することが可能になります( 17 行目~ 18 行目と下に示す出力結果参照).このプログラム内の出力文によって,以下に示すような結果が得られます.
      オブジェクト
         前 n 1
            x 1 2 3
         後 n 4
            x 5 2 3					
    5. 関数名( sort )
      01	#############################
      02	# データの比較(昇順)      #
      03	# a > bの場合に0以外(真) #
      04	#############################
      05	ascend = Proc.new { |a, b| a > b }
      06	
      07	#############################
      08	# データの比較(降順)      #
      09	# a < bの場合に0以外(真) #
      10	#############################
      11	descend = Proc.new { |a, b|
      12		a < b;
      13	}
      14	
      15	#################################################################
      16	# バブルソート                                                  #
      17	#      n : データの数                                           #
      18	#      data : データ                                            #
      19	#      compare : 比較を行う関数                                 #
      20	# バブルソートの手順                                            #
      21	#     1)配列data[i]にn個のデータが入っているものとする.   #
      22	#        i=0,1,・・・,n-1                                  #
      23	#     2)i番目のデータとi+1番目のデータを比較し,もし,     #
      24	#        data[i+1] < data[i] (昇順の場合)            #
      25	#      であればそれらのデータを交換する. i=0,1,・・・,n-2  #
      26	#        →この結果,data[n-1]に最も大きなデータが入る  #
      27	#              ことになる                                       #
      28	#     3)次に,n-1個のデータに対し上の処理を繰り返す.      #
      29	#     4)同様に,n-2,n-3,・・・個のデータに対して同じ処理 #
      30	#        を繰り返す                                             #
      31	#################################################################
      32	def func5(n, data, &compare)
      33		sw = 0;
      34	
      35		if n > 1 then
      36			i1 = 0;
      37			while i1 < n-1 do
      38				if compare.call(data[i1], data[i1+1]) then
      39					sw         = 1;
      40					x          = data[i1];
      41					data[i1]   = data[i1+1];
      42					data[i1+1] = x;
      43				end
      44				i1 += 1;
      45			end
      46		end
      47	
      48		if sw > 0 then
      49			func5(n-1, data, &compare);
      50		end
      51	end
      52	
      53	printf("関数名(sort)\n");
      54	a7 = Array[3, 2, 5, 4, 1];
      55	a8 = Array[3, 2, 5, 4, 1];
      56	printf("   前 %d %d %d %d %d\n", a7[0], a7[1], a7[2], a7[3], a7[4]);
      57	printf("   前 %d %d %d %d %d\n", a8[0], a8[1], a8[2], a8[3], a8[4]);
      58	func5(5, a7, &ascend);   # 昇順
      59	#func5(5, a7) { |a, b| a > b }   # 昇順
      60	#func5(5, a7) do |a, b| a > b end   # 昇順
      61	func5(5, a8, &descend);   # 降順
      62	printf("   後 %d %d %d %d %d\n", a7[0], a7[1], a7[2], a7[3], a7[4]);
      63	printf("   後 %d %d %d %d %d\n", a8[0], a8[1], a8[2], a8[3], a8[4]);
      				
        関数名を関数の引数とした場合の例です.ただし,Ruby には,全く同じ機能が存在しないため,ブロック付きメソッド呼び出しという機能を利用しています.バブルソートを行う関数 func5 に,データの数( 5 ),ソートすべきデータ( a7,a8 ),及び,比較を実行するためのブロック名( ascend,descend )を引数として渡しています(最後の引数として渡す必要がある).なお,05 行目の記述を行わず,59 行目,または,60 行目のように記述しても構いません( descend についても同様).このプログラム内の出力文によって,以下に示すような結果が得られます.正しくソートが行われているのが分かると思います.
      関数名(sort)
         前 3 2 5 4 1
         前 3 2 5 4 1
         後 1 2 3 4 5
         後 5 4 3 2 1					
    6. 関数名(ニュートン法)
      01	######################
      02	# 関数値と微分の計算 #
      03	######################
      04	snx = Proc.new { |sw, x|
      05		if sw == 0 then
      06			Math.exp(x) - 3.0 * x;
      07		else
      08			Math.exp(x) - 3.0;
      09		end
      10	}
      11	
      12	#####################################################
      13	# Newton法による非線形方程式(f(x)=0)の解            #
      14	#      x0 : 初期値                                  #
      15	#      eps1 : 終了条件1(|x(k+1)-x(k)|<eps1)   #
      16	#      eps2 : 終了条件2(|f(x(k))|<eps2)       #
      17	#      max : 最大試行回数                           #
      18	#      ind : 実際の試行回数                         #
      19	#            (負の時は解を得ることができなかった) #
      20	#      fn : f(x)を計算する関数名                    #
      21	#      dfn : f(x)の微分を計算する関数名             #
      22	#      return : 解                                  #
      23	#####################################################
      24	def func6(x0, eps1, eps2, max, ind, &f)
      25		x      = x0;
      26		x1     = x0;
      27		sw     = 0;
      28		ind[0] = 0;
      29	
      30		while sw == 0 && ind[0] >= 0 do
      31			sw      = 1;
      32			ind[0] += 1;
      33			g       = f.call(0, x1);
      34			if g.abs() > eps2 then
      35				if ind[0] <= max then
      36					dg = f.call(1, x1);
      37					if dg.abs() > eps2 then
      38						x = x1 - g / dg;
      39						if (x-x1).abs() > eps1 && (x-x1).abs() > eps1*x.abs() then
      40							x1 = x;
      41							sw = 0;
      42						end
      43					else
      44						ind[0] = -1;
      45					end
      46				else
      47					ind[0] = -1;
      48				end
      49			end
      50		end
      51	
      52		return x;
      53	end
      54	
      55	printf("関数名(Newton 法)\n");
      56	eps1 = 1.0e-7;
      57	eps2 = 1.0e-10;
      58	x0   = 0.0;
      59	max  = 20;
      60	ind  = [0];
      61	x    = func6(x0, eps1, eps2, max, ind, &snx);
      62	printf("   回数=%d  x=%f  関数値=%f  微係数=%f\n", ind[0], x, snx.call(0, x), snx.call(1, x));
      				
        上と同様,関数名を関数の引数とした場合の例です.この例においては,ニュートン法によって非線形方程式 f(x) = ex - 3x = 0 の解を求めています.解を求めるための関数 func6 に,初期値( x0 ),収束判定のための閾値( eps1,eps2 ),最大試行回数( max ),収束までの実行回数を返す配列変数( ind ),及び,関数値と関数の微分値を計算するためのブロック名( snx )を引数として渡しています.なお,関数に渡すことが可能なブロックは一つだけのため,関数値及び関数の微分値を一つのブロック内で計算しています.このプログラム内の出力文によって,以下に示すような結果が得られます.
      関数名(Newton 法)
         回数=5  x=0.619061  関数値=-0.000000  微係数=-1.142816					

  6. Python

    1. 基本型データ,文字列
      01	# -*- coding: UTF-8 -*-
      02	
      03	##################################
      04	# 2 つの整数の和                 #
      05	#      u, v : 和を計算するデータ #
      06	#      t : 文字列                #
      07	#      return : u + v            #
      08	##################################
      09	def func1(u, v, t) :
      10		t = t.replace("a", "x")
      11		u = 100
      12		a = u + v
      13		return a
      14	
      15	print("基本型,文字列")
      16	a1 = 10
      17	b1 = 20
      18	c1 = 0
      19	s1 = "abc"
      20	print("   前", a1, b1, c1, s1)
      21	c1 = func1(a1, b1, s1)
      22	print("   後", a1, b1, c1, s1)
      				
        基本型データ及び文字列を関数の引数とした場合の例です.加算を行う変数 a1,b1 と s1 を関数 func1 に引数として渡し,変数 c1 に関数の戻り値として結果が代入されています.また,s1 は,文字列です.このプログラム内の出力文によって,以下に示すような結果が得られます.この結果は,関数を呼ぶ前と呼んだ後における変数 a1,b1,c1,及び,s1 の値を示しています.a1,b1 のコピーが引数として関数に渡されるため,11 行目において,変数 u (変数 a1 のコピー)の値を変更していますが,変数 a1 はその影響を受けていません.文字列においても同様です.
      基本型,文字列
         前 10 20 0 abc
         後 10 20 120 abc					
    2. 1 次元配列
      01	# -*- coding: UTF-8 -*-
      02	import numpy as np
      03	
      04	########################
      05	# 1 次元配列の要素の和 #
      06	#      n : 要素数      #
      07	#      u, v : 配列     #
      08	########################
      09	def func2(n, u, v) :
      10		for i1 in range(0, n) :
      11			u[n] += u[i1]
      12			v[n] += v[i1]
      13	
      14	print("1 次元配列")
      15	a2 = [1, 2, 3, 0]
      16	b2 = np.array([1, 2, 3, 0])
      17	print("   前 a2", a2[0], a2[1], a2[2], a2[3])
      18	print("      b2", b2[0], b2[1], b2[2], b2[3])
      19	func2(3, a2, b2)
      20	print("   後 a2", a2[0], a2[1], a2[2], a2[3])
      21	print("      b2", b2[0], b2[1], b2[2], b2[3])
      				
        1 次元配列を関数の引数とした場合の例です.関数に対して,0 以外の値が入っている要素の数( 3 ),リスト型( list )を使用した 1 次元配列( a2 ),及び,NumPy を使用した 1 次元配列( b2 )を引数として渡しています.Python における配列の場合は,記憶領域のアドレスが渡されることと同等ですので,関数内においてその各要素の値を変更可能です.そのため,1 番目から 3 番目までの要素の和を 4 番目の要素に記憶しています.このプログラム内の出力文によって,以下に示すような結果が得られます.
      1 次元配列
         前 a2 1 2 3 0
            b2 1 2 3 0
         後 a2 1 2 3 6
            b2 1 2 3 6					
    3. 2 次元配列
      01	# -*- coding: UTF-8 -*-
      02	
      03	########################
      04	# 2 次元配列の要素の和 #
      05	#      n : 行数        #
      06	#      m : 列数        #
      07	#      u : 配列        #
      08	########################
      09	def func3(n, m, u) :
      10		for i1 in range(0, n) :
      11			for i2 in range(0, m) :
      12				u[i1][m] += u[i1][i2];
      13	
      14	print("2 次元配列")
      15	a3 = [[1, 2, 3, 0], [4, 5, 6, 0]]
      16	print("   前", a3[0][0], a3[0][1], a3[0][2], a3[0][3])
      17	print("     ", a3[1][0], a3[1][1], a3[1][2], a3[1][3])
      18	func3(2, 3, a3);
      19	print("   後", a3[0][0], a3[0][1], a3[0][2], a3[0][3])
      20	print("     ", a3[1][0], a3[1][1], a3[1][2], a3[1][3])
      				
        リスト型( list )を使用した 2 次元配列を関数の引数とした場合の例です.関数に対して,行の数( 2 ),列の数( 3,0 でない列の数 ),2 次元配列( a3 )を引数としています.Python においては,基本型変数のアドレスを渡す方法や参照渡しといった方法を利用できないため,各行の最後の要素に,その行に含まれる要素の和を代入しています.このプログラム内の出力文によって,以下に示すような結果が得られます.
      2 次元配列
         前 1 2 3 0
            4 5 6 0
         後 1 2 3 6
            4 5 6 15					
    4. クラスのオブジェクト
      01	# -*- coding: UTF-8 -*-
      02	
      03	##################
      04	# クラス Example #
      05	##################
      06	class Example :
      07		def init(self, n) :
      08			self.n = n
      09			self.x = [1, 2, 3]
      10	
      11	##########################
      12	# オブジェクトの値変更   #
      13	#      x1 : オブジェクト #
      14	##########################
      15	def func4(x1) :
      16		x1.n    = 4
      17		x1.x[0] = 5
      18	
      19	print("オブジェクト")
      20	a4 = Example()
      21	a4.init(1)
      22	print("   前 n", a4.n)
      23	print("      x ", a4.x[0], a4.x[1], a4.x[2])
      24	func4(a4)
      25	print("   後 n", a4.n)
      26	print("      x ", a4.x[0], a4.x[1], a4.x[2])
      				
        クラスのオブジェクト(クラスの定義は,06 行目~ 09 行目)を関数の引数とした場合の例です.この例では,オブジェクト( a4 )だけを引数として渡しています.Python においては,C++ とは異なり,オブジェクトのアドレスが渡される場合と等価になります.従って,関数側で関数を呼んだ側のオブジェクトの値を変更することが可能になります( 16 行目~ 17 行目と下に示す出力結果参照).このプログラム内の出力文によって,以下に示すような結果が得られます.
      オブジェクト
         前 n 1
            x  1 2 3
         後 n 4
            x  5 2 3					
    5. 関数名( sort )
      01	# -*- coding: UTF-8 -*-
      02	
      03	########################
      04	# データの比較(昇順) #
      05	# a > bの場合に真      #
      06	########################
      07	def ascend(a, b) :
      08		tf = False
      09		if a > b :
      10			tf = True
      11		return tf
      12	
      13	########################
      14	# データの比較(降順) #
      15	# a < bの場合に真      #
      16	########################
      17	def descend(a, b) :
      18		tf = False
      19		if a < b :
      20			tf = True
      21		return tf
      22	
      23	#################################################################
      24	# バブルソート                                                  #
      25	#      n : データの数                                           #
      26	#      data : データ                                            #
      27	#      compare : 比較を行う関数                                 #
      28	# バブルソートの手順                                            #
      29	#     1)配列data[i]にn個のデータが入っているものとする.   #
      30	#        i=0,1,・・・,n-1                                  #
      31	#     2)i番目のデータとi+1番目のデータを比較し,もし,     #
      32	#        data[i+1] < data[i] (昇順の場合)            #
      33	#      であればそれらのデータを交換する. i=0,1,・・・,n-2  #
      34	#        →この結果,data[n-1]に最も大きなデータが入る  #
      35	#              ことになる                                       #
      36	#     3)次に,n-1個のデータに対し上の処理を繰り返す.      #
      37	#     4)同様に,n-2,n-3,・・・個のデータに対して同じ処理 #
      38	#        を繰り返す                                             #
      39	#################################################################
      40	def func5(n, data, compare) :
      41		sw = 0;
      42	
      43		if n > 1 :
      44			for i1 in range(0, n-1) :
      45				if compare(data[i1], data[i1+1]) : 
      46					sw         = 1
      47					x          = data[i1]
      48					data[i1]   = data[i1+1]
      49					data[i1+1] = x
      50	
      51		if sw > 0 :
      52			func5(n-1, data, compare)
      53	
      54	print("関数名(sort)")
      55	a7 = [3, 2, 5, 4, 1]
      56	a8 = [3, 2, 5, 4, 1]
      57	print("   前", a7[0], a7[1], a7[2], a7[3], a7[4])
      58	print("   前", a8[0], a8[1], a8[2], a8[3], a8[4])
      59	func5(5, a7, ascend)   # 昇順
      60	func5(5, a8, descend)   # 降順
      61	print("   後", a7[0], a7[1], a7[2], a7[3], a7[4])
      62	print("   後", a8[0], a8[1], a8[2], a8[3], a8[4])
      				
        関数名を関数の引数とした場合の例です.バブルソートを行う関数 func5 に,データの数( 5 ),ソートすべきデータ( a7,a8 ),及び,比較を実行するための関数名( ascend,descend )を引数として渡しています.このプログラム内の出力文によって,以下に示すような結果が得られます.正しくソートが行われているのが分かると思います.
      関数名(sort)
         前 3 2 5 4 1
         前 3 2 5 4 1
         後 1 2 3 4 5
         後 5 4 3 2 1					
    6. 関数名(ニュートン法)
      01	# -*- coding: UTF-8 -*-
      02	from math import *
      03	
      04	########################
      05	# 関数値(f(x))の計算 #
      06	########################
      07	def snx(x) :
      08		return exp(x) - 3.0 * x
      09	
      10	####################
      11	# 関数の微分の計算 #
      12	####################
      13	def dsnx(x) :
      14		return exp(x) - 3.0
      15	
      16	#####################################################
      17	# Newton法による非線形方程式(f(x)=0)の解            #
      18	#      fn : f(x)を計算する関数名                    #
      19	#      dfn : f(x)の微分を計算する関数名             #
      20	#      x0 : 初期値                                  #
      21	#      eps1 : 終了条件1(|x(k+1)-x(k)|<eps1)   #
      22	#      eps2 : 終了条件2(|f(x(k))|<eps2)       #
      23	#      max : 最大試行回数                           #
      24	#      ind : 実際の試行回数                         #
      25	#            (負の時は解を得ることができなかった) #
      26	#      return : 解                                  #
      27	#####################################################
      28	def func6(f, df, x0, eps1, eps2, max, ind) :
      29		x      = x0
      30		x1     = x0
      31		sw     = 0
      32		ind[0] = 0
      33	
      34		while sw == 0 and ind[0] >= 0 :
      35			sw      = 1
      36			ind[0] += 1
      37			g       = f(x1)
      38			if abs(g) > eps2 :
      39				if ind[0] <= max :
      40					dg = df(x1);
      41					if abs(dg) > eps2 :
      42						x = x1 - g / dg
      43						if abs(x-x1) > eps1 and abs(x-x1) > eps1*abs(x) :
      44							x1 = x
      45							sw = 0
      46					else :
      47						ind[0] = -1
      48				else :
      49					ind[0] = -1
      50	
      51		return x
      52	
      53	print("関数名(Newton 法)")
      54	eps1 = 1.0e-7
      55	eps2 = 1.0e-10
      56	x0   = 0.0
      57	max  = 20
      58	ind  = [0]
      59	x    = func6(snx, dsnx, x0, eps1, eps2, max, ind)
      60	print("   回数=", ind[0], "x=", x, "関数値=", snx(x), "微係数=", dsnx(x))
      				
        上と同様,関数名を関数の引数とした場合の例です.この例においては,ニュートン法によって非線形方程式 f(x) = ex - 3x = 0 の解を求めています.解を求めるための関数 func6 に,関数値を計算するための関数名( snx ),関数の微分値を計算するための関数名( dsnx ),初期値( x0 ),収束判定のための閾値( eps1,eps2 ),最大試行回数( max ),及び,収束までの実行回数を返す配列変数( ind )を引数として渡しています.このプログラム内の出力文によって,以下に示すような結果が得られます.
      関数名(Newton 法)
         回数= 5 x= 0.6190612867359452 関数値= -2.220446049250313e-16 微係数= -1.1428161397921646					

  7. C#

    1. 基本型データ,文字列
      01	using System;
      02	
      03	class Program
      04	{
      05		static void Main()
      06		{
      07			Test1 ts = new Test1();
      08		}
      09	}
      10	
      11	class Test1
      12	{
      13		public Test1()
      14		{
      15			Console.WriteLine("基本型,文字列");
      16			int a1 = 10, b1 = 20, c1 = 0, d1 = 0;
      17			string s1 = "abc", s2 = "abc";
      18			Console.WriteLine("   前 " + a1 + " b1 " + b1 + " c1 " + c1 + " s1 " + s1 + " s2 " + s2);
      19			d1 = func1(a1, b1, ref c1, s1, ref s2);
      20			Console.WriteLine("   前 " + a1 + " b1 " + b1 + " c1 " + c1 + " d1 " + d1 + " s1 " + s1 + " s2 " + s2);
      21		}
      22	
      23		/**********************************/
      24		/* 2 つの整数の和                 */
      25		/*      u, v : 和を計算するデータ */
      26		/*      w : 結果                  */
      27		/*      t1, t2 : 文字列           */
      28		/*      return : u + v            */
      29		/**********************************/
      30		int func1(int u, int v, ref int w, string t1, ref string t2)
      31		{
      32			t1 = t1.ToUpper();
      33			t2 = t2.ToUpper();
      34			u  = 100;
      35			w  = u + v;
      36			return w;
      37		}
      38	}
      				
        基本型データ及び文字列を関数の引数とした場合の例です.19 行目と 30 行目から明らかなように,変数 a1,b1,s1 はその値,変数 c1,s2 に関しては参照渡しをしており,19 行目の変数 d1 には,関数の戻り値が代入されます.変数 s1 と s2 は文字列です.このプログラム内の出力文によって,以下に示すような結果が得られます.この結果は,関数を呼ぶ前と呼んだ後における変数 a1,b1,c1,d1,s1,及び,s2 の値を示しています.
      基本型,文字列
         前 10 b1 20 c1 0 s1 abc s2 abc
         前 10 b1 20 c1 120 d1 120 s1 abc s2 ABC					
        34 行目において,変数 u (変数 a1 のコピー)の値を変更していますが,変数 a1 はその影響を受けていません.しかし,参照渡しをした変数 c1,s2 は,35 行目,及び,33 行目の処理によって,その値が変化しています.当然,36 行目の return 文による戻り値を代入した変数 d1 の値も変化します.
    2. 1 次元配列
      01	using System;
      02	using System.Collections.Generic;
      03	
      04	class Program
      05	{
      06		static void Main()
      07		{
      08			Test1 ts = new Test1();
      09		}
      10	}
      11	
      12	class Test1
      13	{
      14		public Test1()
      15		{
      16			Console.WriteLine("1 次元配列");
      17			int[] a2 = {1, 2, 3, 0};
      18			List  b2 = new List  ();
      19			for (int i1 = 0; i1 < 3; i1++)
      20				b2.Add(10 * (i1 + 1));
      21			b2.Add(0);
      22			Console.WriteLine("   前 a2 " + a2[0] + " " + a2[1] + " " + a2[2] + " " + a2[3]);
      23			Console.WriteLine("      b2 " + b2[0] + " " + b2[1] + " " + b2[2] + " " + b2[3]);
      24			func2(3, a2, b2);
      25			Console.WriteLine("   後 a2 " + a2[0] + " " + a2[1] + " " + a2[2] + " " + a2[3]);
      26			Console.WriteLine("      b2 " + b2[0] + " " + b2[1] + " " + b2[2] + " " + b2[3]);
      27		}
      28	
      29		/************************/
      30		/* 1 次元配列の要素の和 */
      31		/*      n : 要素数      */
      32		/*      u : 配列        */
      33		/*      w : List        */
      34		/************************/
      35		void func2(int n, int[] u, List  w)
      36		{
      37			int s = 0;
      38			for (int i1 = 0; i1 < n; i1++) {
      39				u[n] += u[i1];
      40				s    += w[i1];
      41			}
      42			w[n] = s;
      43		}
      44	}
      				
        1 次元配列を関数の引数とした場合の例です.関数に対して,0 以外の値が入っている要素の数( 3 ),通常の 1 次元配列( a2 ),及び,List クラスのオブジェクト( b2 )を引数として渡しています.配列や List クラスの場合,記憶領域のアドレスが渡されることと同等ですので,関数内においてその各要素の値を変更可能です.そのため,1 番目から 3 番目までの要素の和を 4 番目の要素に記憶しています.このプログラム内の出力文によって,以下に示すような結果が得られます.
      1 次元配列
         前 a2 1 2 3 0
            b2 10 20 30 0
         後 a2 1 2 3 6
            b2 10 20 30 60					
    3. 2 次元配列
      01	using System;
      02	
      03	class Program
      04	{
      05		static void Main()
      06		{
      07			Test1 ts = new Test1();
      08		}
      09	}
      10	
      11	class Test1
      12	{
      13		public Test1()
      14		{
      15			Console.WriteLine("2 次元配列");
      16			int[][] a4 = new int[][] {
      17				new int[] {1, 2, 3, 0},
      18				new int[] {4, 5, 6, 0}
      19			};
      20			int[,] a5 = {{1, 2, 3, 0}, {4, 5, 6, 0}};
      21			Console.WriteLine("   前 a4 " + a4[0][0] + " " + a4[0][1] + " " + a4[0][2] + " " + a4[0][3]);
      22			Console.WriteLine("         " + a4[1][0] + " " + a4[1][1] + " " + a4[1][2] + " " + a4[1][3]);
      23			func3(2, 3, a4);
      24			Console.WriteLine("   後 a4 " + a4[0][0] + " " + a4[0][1] + " " + a4[0][2] + " " + a4[0][3]);
      25			Console.WriteLine("         " + a4[1][0] + " " + a4[1][1] + " " + a4[1][2] + " " + a4[1][3]);
      26			Console.WriteLine("   前 a5 " + a5[0,0] + " " + a5[0,1] + " " + a5[0,2] + " " + a5[0,3]);
      27			Console.WriteLine("         " + a5[1,0] + " " + a5[1,1] + " " + a5[1,2] + " " + a5[1,3]);
      28			func4(2, 3, a5);
      29			Console.WriteLine("   後 a5 " + a5[0,0] + " " + a5[0,1] + " " + a5[0,2] + " " + a5[0,3]);
      30			Console.WriteLine("         " + a5[1,0] + " " + a5[1,1] + " " + a5[1,2] + " " + a5[1,3]);
      31		}
      32	
      33		/****************************/
      34		/* 2 次元配列の要素の和     */
      35		/*      n : 行数            */
      36		/*      m : 列数            */
      37		/*      u : 配列            */
      38		/*      u[i1][m] : 各行の和 */
      39		/****************************/
      40		void func3(int n, int m, int[][] u)
      41		{
      42			for (int i1 = 0; i1 < n; i1++) {
      43				for (int i2 = 0; i2 < m; i2++)
      44					u[i1][m] += u[i1][i2];
      45			}
      46		}
      47	
      48		/***************************/
      49		/* 2 次元配列の要素の和    */
      50		/*      n : 行数           */
      51		/*      m : 列数           */
      52		/*      u : 配列           */
      53		/*      u[i1,m] : 各行の和 */
      54		/***************************/
      55		void func4(int n, int m, int[,] u)
      56		{
      57			for (int i1 = 0; i1 < n; i1++) {
      58				for (int i2 = 0; i2 < m; i2++)
      59					u[i1,m] += u[i1,i2];
      60			}
      61		}
      62	}
      				
        2 次元配列を関数の引数とした場合の例です.関数に対して,行の数( 2 ),0 でない列の数( 3 ),2 次元配列 a4[][]( func3 ),または,a5[*,*]( func4 ) を引数としています.配列の場合,記憶領域のアドレスが渡されることと同等ですので,各行における要素の和を,その行の最後の要素に代入して返しています.このプログラム内の出力文によって,以下に示すような結果が得られます.
      2 次元配列
         前 a4 1 2 3 0
               4 5 6 0
         後 a4 1 2 3 6
               4 5 6 15
         前 a5 1 2 3 0
               4 5 6 0
         後 a5 1 2 3 6
               4 5 6 15					
    4. クラスのオブジェクト
      01	using System;
      02	
      03	class Program
      04	{
      05		static void Main()
      06		{
      07			Test1 ts = new Test1();
      08		}
      09	}
      10	
      11	class Test1
      12	{
      13		public Test1()
      14		{
      15			Console.WriteLine("オブジェクト");
      16			Example a6 = new Example(3);
      17			Console.WriteLine("   前 n " + a6.n);
      18			Console.WriteLine("      x " + " " + a6.x[0] + " " + a6.x[1] + " " + a6.x[2]);
      19			func5(a6);
      20			Console.WriteLine("   前 n " + a6.n);
      21			Console.WriteLine("      x " + " " + a6.x[0] + " " + a6.x[1] + " " + a6.x[2]);
      22		}
      23	
      24		/**************************/
      25		/* オブジェクトの値変更   */
      26		/*      x1 : オブジェクト */
      27		/**************************/
      28		void func5(Example x1)
      29		{
      30			x1.n    = 10;
      31			x1.x[0] = 4;
      32		}
      33	}
      34	
      35	/******************/
      36	/* クラス Example */
      37	/******************/
      38	class Example {
      39		public int n;
      40		public int[] x = {0, 1, 2};
      41		public Example(int n1)
      42		{
      43			n = n1;
      44		}
      45	}
      				
        クラスのオブジェクト(クラスの定義は,38 行目~ 45 行目)を関数の引数とした場合の例です.クラスのオブジェクト( a6 )を引数として渡しています.クラスのオブジェクトの場合も,記憶領域のアドレスが渡されることと同等ですので,関数内でその値を変更すれば,関数を呼んだ側の値も変化します.このプログラム内の出力文によって,以下に示すような結果が得られます.
      オブジェクト
         前 n 3
            x  0 1 2
         前 n 10
            x  4 1 2					
    5. 関数名( sort )
      01	using System;
      02	
      03	class Program
      04	{
      05		static void Main()
      06		{
      07			Test1 ts = new Test1();
      08		}
      09	}
      10	
      11	class Test1
      12	{
      13		public Test1()
      14		{
      15			Console.WriteLine("関数名(sort)");
      16			int[] a7 = {3, 2, 5, 4, 1};
      17			int[] a8 = {3, 2, 5, 4, 1};
      18			Console.WriteLine("   前 " + a7[0] + " " + a7[1] + " " + a7[2] + " " + a7[3] + " " + a7[4]);
      19			Console.WriteLine("   前 " + a8[0] + " " + a8[1] + " " + a8[2] + " " + a8[3] + " " + a8[4]);
      20			func6(5, a7, ascend);   // 昇順
      21			func6(5, a8, descend);   // 降順
      22			Console.WriteLine("   後 " + a7[0] + " " + a7[1] + " " + a7[2] + " " + a7[3] + " " + a7[4]);
      23			Console.WriteLine("   後 " + a8[0] + " " + a8[1] + " " + a8[2] + " " + a8[3] + " " + a8[4]);
      24		}
      25	
      26		/*****************************/
      27		/* データの比較(昇順)      */
      28		/* a > bの場合に0以外(真) */
      29		/*****************************/
      30		bool ascend(int a, int b)
      31		{
      32			return a > b;
      33		}
      34		
      35		/*****************************/
      36		/* データの比較(降順)      */
      37		/* a < bの場合に0以外(真) */
      38		/*****************************/
      39		bool descend(int a, int b)
      40		{
      41			return a < b;
      42		}
      43		
      44		/***********************************/
      45		/* 2つのデータを交換する          */
      46		/*      a,b : 2つのデータ(参照) */
      47		/***********************************/
      48		void swap(ref int a, ref int b)
      49		{
      50			int temp = a;
      51			a        = b;
      52			b        = temp;
      53		}
      54		
      55		/*****************************************************************/
      56		/* バブルソート                                                  */
      57		/*      n : データの数                                           */
      58		/*      data : データ                                            */
      59		/*      compare : 比較を行う関数                                 */
      60		/* バブルソートの手順                                            */
      61		/*     1)配列data[i]にn個のデータが入っているものとする.   */
      62		/*        i=0,1,・・・,n-1                                  */
      63		/*     2)i番目のデータとi+1番目のデータを比較し,もし,     */
      64		/*        data[i+1] < data[i] (昇順の場合)            */
      65		/*      であればそれらのデータを交換する. i=0,1,・・・,n-2  */
      66		/*        →この結果,data[n-1]に最も大きなデータが入る  */
      67		/*              ことになる                                       */
      68		/*     3)次に,n-1個のデータに対し上の処理を繰り返す.      */
      69		/*     4)同様に,n-2,n-3,・・・個のデータに対して同じ処理 */
      70		/*        を繰り返す                                             */
      71		/*****************************************************************/
      72		void func6(int n, int[] data, Func<int, int, bool> compare)
      73		{
      74			int sw = 0;
      75		
      76			if (n > 1) {
      77				for (int i1 = 0; i1 < n-1; i1++) {
      78					if (compare(data[i1], data[i1+1])) {
      79						sw = 1;
      80						swap(ref data[i1], ref data[i1+1]);
      81					}
      82				}
      83			}
      84		
      85			if (sw > 0)
      86				func6(n-1, data, compare);
      87		}
      88	}
      				
        関数名を関数の引数とした場合の例です.バブルソートを行う関数 func6 に,データの数( 5 ),ソートすべきデータ( a7,a8 ),及び,比較を実行するための関数名( ascend,descend )を引数として渡しています.このプログラム内の出力文によって,以下に示すような結果が得られます.正しくソートが行われているのが分かると思います.
      関数名(sort)
         前 3 2 5 4 1
         前 3 2 5 4 1
         後 1 2 3 4 5
         後 5 4 3 2 1					
    6. 関数名(ニュートン法)
      01	using System;
      02	
      03	class Program
      04	{
      05		static void Main()
      06		{
      07			Test1 ts = new Test1();
      08		}
      09	}
      10	
      11	class Test1
      12	{
      13		public Test1()
      14		{
      15			Console.WriteLine("関数名(Newton 法)");
      16			double eps1 = 1.0e-7;
      17			double eps2 = 1.0e-10;
      18			double x0   = 0.0;
      19			int max     = 20;
      20			int ind     = 0;
      21			double x = func7(x0, eps1, eps2, max, ref ind, snx, 0.0, dsnx, 0.0);
      22			Console.WriteLine("   回数=" + ind + " x=" + x + " 関数値=" + snx(x) + " 微係数=" + dsnx(x));
      23		}
      24		
      25		/************************/
      26		/* 関数値(f(x))の計算 */
      27		/************************/
      28		double snx(double x)
      29		{
      30			double y = Math.Exp(x) - 3.0 * x;
      31			return y;
      32		}
      33		
      34		/********************/
      35		/* 関数の微分の計算 */
      36		/********************/
      37		double dsnx(double x)
      38		{
      39			double y = Math.Exp(x) - 3.0;
      40			return y;
      41		}
      42		
      43		/*****************************************************/
      44		/* Newton法による非線形方程式(f(x)=0)の解            */
      45		/*      x0 : 初期値                                  */
      46		/*      eps1 : 終了条件1(|x(k+1)-x(k)|<eps1)   */
      47		/*      eps2 : 終了条件2(|f(x(k))|<eps2)       */
      48		/*      max : 最大試行回数                           */
      49		/*      ind : 実際の試行回数(参照)                 */
      50		/*            (負の時は解を得ることができなかった) */
      51		/*      fn : f(x)を計算する関数名                    */
      52		/*      dfn : f(x)の微分を計算する関数名             */
      53		/*      return : 解                                  */
      54		/*****************************************************/
      55		double func7(double x0, double eps1, double eps2, int max, ref int ind,
      56		             Func fn, Func dfn)
      57		{
      58			double x = x0, x1 = x0;
      59			int sw   = 0;
      60			ind      = 0;
      61		
      62			while (sw == 0 && ind >= 0) {
      63				sw   = 1;
      64				ind += 1;
      65				double g = fn(x1);
      66				if (Math.Abs(g) > eps2) {
      67					if (ind <= max) {
      68						double dg = dfn(x1);
      69						if (Math.Abs(dg) > eps2) {
      70							x = x1 - g / dg;
      71							if (Math.Abs(x-x1) > eps1 && Math.Abs(x-x1) > eps1*Math.Abs(x)) {
      72								x1 = x;
      73								sw = 0;
      74							}
      75						}
      76						else
      77							ind = -1;
      78					}
      79					else
      80						ind = -1;
      81				}
      82			}
      83		
      84			return x;
      85		}
      86	}
      				
        上と同様,関数名を関数の引数とした場合の例です.この例においては,ニュートン法によって非線形方程式 f(x) = ex - 3x = 0 の解を求めています.解を求めるための関数 func7 に,初期値( x0 ),収束判定のための閾値( eps1,eps2 ),最大試行回数( max ),収束までの実行回数を返す変数( ind ),関数値を計算するための関数名( snx ),関数の微分値を計算するための関数名( dsnx )を引数として渡しています.このプログラム内の出力文によって,以下に示すような結果が得られます.
      関数名(Newton 法)
         回数=5 x=0.619061286735945 関数値=-2.22044604925031E-16 微係数=-1.14281613979216					

  8. VB

    1. 基本型データ,文字列
      01	Module Test
      02		Sub Main()
      03			Console.WriteLine("基本型,文字列")
      04			DIm a1 As Integer = 10
      05			DIm b1 As Integer = 20
      06			DIm c1 As Integer = 0
      07			DIm d1 As Integer = 0
      08			DIm s1 As String  = "abc"
      09			DIm s2 As String  = "abc"
      10			Console.WriteLine("   前 " & a1 & " b1 " & b1 & " c1 " & c1 & " s1 " & s1 & " s2 " & s2)
      11			d1 = func1(a1, b1, c1, s1, s2)
      12	'		func1(a1, b1, c1, s1, s2)
      13			Console.WriteLine("   後 " & a1 & " b1 " & b1 & " c1 " & c1 & " s1 " & s1 & " s2 " & s2 & " d1 " & d1)
      14		End Sub
      15	
      16		''''''''''''''''''''''''''''''''''
      17		' 2 つの整数の和                 '
      18		'      u, v : 和を計算するデータ '
      19		'      w : 結果                  '
      20		'      t1, t2 : 文字列           '
      21		'      return : u + v            '
      22		''''''''''''''''''''''''''''''''''
      23		Function func1(ByVal u As Integer, ByVal v As Integer, ByRef w As Integer,
      24		               ByVal t1 As String, ByRef t2 As String) As Integer
      25	'	Function func1(u As Integer, v As Integer, ByRef w As Integer,
      26	'	               t1 As String, ByRef t2 As String) As Integer
      27	'	Function func1(ByVal u As Integer, ByVal v As Integer, ByRef w As Integer,
      28	'	               ByVal t1 As String, ByRef t2 As String)
      29	'	Sub func1(ByVal u As Integer, ByVal v As Integer, ByRef w As Integer,
      30	'	               ByVal t1 As String, ByRef t2 As String)
      31			Dim a As Integer
      32			u  = 100
      33			a  = u + v
      34			w  = a
      35			t1 = Replace(t1, "a", "x")
      36			t2 = Replace(t2, "a", "x")
      37			Return a   ' 戻り値を指定しない場合は必要ないが警告が出力される
      38		End Function
      39	'	End Sub
      40	End Module
      				
        VB には,関数の記述方法として 2 種類存在します.関数の戻り値が存在する場合は,
      Function ...
      	・・・・・
      End Function					
      のように記述し,存在しない場合は,
      Sub ...
      	・・・・・
      End Sub					
      を使用します.戻り値がない場合に,Function を使用すると( 27,28 行目),警告メッセージが出力され,戻り値がある場合に,Sub を使用すると,エラーになります.また,引数に関しては,値渡し( ByVal ),または,参照渡し( ByRef )のいずれかを選択可能です.25,26 行目のように,ByVal は省略可能です.

        基本型データ及び文字列を関数の引数とした場合の例です.11 行目と 23,24 行目から明らかなように,変数 a1,b1,s1 はその値,変数 c1,s2 に関しては参照渡しをしており,11 行目の変数 d1 には,関数の戻り値が代入されます.変数 s1 と s2 は文字列です.このプログラム内の出力文によって,以下に示すような結果が得られます.この結果は,関数を呼ぶ前と呼んだ後における変数 a1,b1,c1,d1,s1,及び,s2 の値を示しています.
      基本型,文字列
         前 10 b1 20 c1 0 s1 abc s2 abc
         前 10 b1 20 c1 120 d1 120 s1 abc s2 ABC					
        32 行目において,変数 u (変数 a1 のコピー)の値を変更していますが,変数 a1 はその影響を受けていません.しかし,参照渡しをした変数 c1,s2 は,34 行目,及び,36 行目の処理によって,その値が変化しています.当然,37 行目の return 文による戻り値を代入した変数 d1 の値も変化します.
    2. 1 次元配列
      01	Imports System.Collections.Generic
      02	
      03	Module Test
      04		Sub Main()
      05			Console.WriteLine("1 次元配列")
      06			DIm a2() As Integer = {1, 2, 3, 0}
      07			Dim b2 As New List(Of Integer)
      08			b2.Add(10)
      09			b2.Add(20)
      10			b2.Add(30)
      11			b2.Add(0)
      12			Console.WriteLine("   前 a2 " & a2(0) & " " & a2(1) & " " & a2(2) & " " & a2(3))
      13			Console.WriteLine("   前 b2 " & b2(0) & " " & b2(1) & " " & b2(2) & " " & b2(3))
      14			func2(4, a2, b2)
      15			Console.WriteLine("   後 a2 " & a2(0) & " " & a2(1) & " " & a2(2) & " " & a2(3))
      16			Console.WriteLine("   後 b2 " & b2(0) & " " & b2(1) & " " & b2(2) & " " & b2(3))
      17		End Sub
      18	
      19		''''''''''''''''''''''''
      20		' 1 次元配列の要素の和 '
      21		'      n : 要素数      '
      22		'      u : 配列        '
      23		'      v : List        '
      24		''''''''''''''''''''''''
      25		Sub func2(n As Integer, u() As Integer, v As List(Of Integer))
      26	'	Sub func2(n As Integer, ByVal u() As Integer, v As List(Of Integer))
      27	'	Sub func2(n As Integer, ByRef u() As Integer, v As List(Of Integer))
      28			For i1 As Integer = 0 To n-2
      29				u(n-1) += u(i1)
      30				v(n-1) += v(i1)
      31			Next
      32		End Sub
      33	End Module
      				
        1 次元配列を関数の引数とした場合の例です.関数に対して,要素の数( 4 ),通常の 1 次元配列( a2 ),及び,List クラスのオブジェクト( b2 )を引数として渡しています.配列や List クラスの場合,記憶領域のアドレスが渡されることと同等ですので,関数内においてその各要素の値を変更可能です.そのため,1 番目から 3 番目までの要素の和を 4 番目の要素に記憶しています.なお,26,27 行目のような指定を行っても,結果は同じです.このプログラム内の出力文によって,以下に示すような結果が得られます.
      1 次元配列
         前 a2 1 2 3 0
         前 b2 10 20 30 0
         後 a2 1 2 3 6
         後 b2 10 20 30 60					
    3. 2 次元配列
      01	Module Test
      02		Sub Main()
      03			Console.WriteLine("2 次元配列")
      04			DIm a3(,) As Integer = {{1, 2, 3, 0}, {4, 5, 6, 0}}
      05			Console.WriteLine("   前 " & a3(0, 3) & " " & a3(1, 3))
      06			func3(2, 3, a3)
      07			Console.WriteLine("   後 " & a3(0, 3) & " " & a3(1, 3))
      08		End Sub
      09	
      10		''''''''''''''''''''''''
      11		' 2 次元配列の要素の和 '
      12		'      n : 行数        '
      13		'      m : 列数        '
      14		'      u : 配列        '
      15		''''''''''''''''''''''''
      16		Sub func3(n As Integer, m As Integer, u(,) As Integer)
      17			For i1 As Integer = 0 To n-1
      18				For i2 As Integer = 0 To m-1
      19					u(i1, m) += u(i1, i2)
      20				Next
      21			Next
      22		End Sub
      23	End Module
      				
        2 次元配列を関数の引数とした場合の例です.関数に対して,行の数( 2 ),0 でない列の数( 3 ),2 次元配列 a3 を引数としています.配列の場合,記憶領域のアドレスが渡されることと同等ですので,各行における要素の和を,その行の最後の要素に代入して返しています.このプログラム内の出力文によって,以下に示すような結果が得られます.
      2 次元配列
         前 0 0
         後 6 15					
    4. クラスのオブジェクト
      01	Module Test
      02		Sub Main()
      03			Console.WriteLine("オブジェクト")
      04			DIm a4 As Example = new Example(1)
      05			Console.WriteLine("   前 " & a4.n & " " & a4.x(0))
      06			func4(a4)
      07			Console.WriteLine("   前 " & a4.n & " " & a4.x(0))
      08		End Sub
      09	
      10		''''''''''''''''''''''''''
      11		' オブジェクトの値変更   '
      12		'      x1 : オブジェクト '
      13		''''''''''''''''''''''''''
      14		Sub func4(x1 As Example)
      15			x1.n    = 0
      16			x1.x(0) = 100
      17		End Sub
      18	
      19		Class Example
      20			Public n As Integer
      21			Public x() As integer = {10, 20, 30}
      22			Public Sub New (ByVal n1 As Integer)
      23				n = n1
      24			End Sub
      25		End Class
      26	End Module
      				
        クラスのオブジェクト(クラスの定義は,19 行目~ 25 行目)を関数の引数とした場合の例です.クラスのオブジェクト( a4 )を引数として渡しています.クラスのオブジェクトの場合も,記憶領域のアドレスが渡されることと同等ですので,関数内でその値を変更すれば,関数を呼んだ側の値も変化します.このプログラム内の出力文によって,以下に示すような結果が得られます.
      オブジェクト
         前 1 10
         前 0 100					
    5. 関数名( sort )
      01	Module Test
      02		Sub Main()
      03			Console.WriteLine("関数名( sort )")
      04			Dim a7() As Integer = {3, 2, 5, 4, 1}
      05			Dim a8() As Integer = {3, 2, 5, 4, 1}
      06			Console.WriteLine("   前 " & a7(0) & " " & a7(1) & " " & a7(2) & " " & a7(3) & " " & a7(4))
      07			Console.WriteLine("   前 " & a8(0) & " " & a8(1) & " " & a8(2) & " " & a8(3) & " " & a8(4))
      08			Dim ascend = Function(v1, v2) As boolean   ' 比較関数(ラムダ式)
      09			                 Return v1 > v2
      10			             End Function
      11			Dim descend = Function(v1, v2) As boolean   ' 比較関数(ラムダ式)
      12			                  Return v1 < v2
      13			              End Function
      14			func6(5, a7, ascend)   ' 昇順
      15			func6(5, a8, descend)   ' 降順
      16	'		func6(5, a7, Function(v1, v2) v1 > v2)   ' 昇順
      17	'		func6(5, a8, Function(v1, v2) v1 < v2)   ' 降順
      18			Console.WriteLine("   前 " & a7(0) & " " & a7(1) & " " & a7(2) & " " & a7(3) & " " & a7(4))
      19			Console.WriteLine("   前 " & a8(0) & " " & a8(1) & " " & a8(2) & " " & a8(3) & " " & a8(4))
      20		End Sub
      21		
      22		'''''''''''''''''''''''''''''''''''
      23		' 2つのデータを交換する          '
      24		'      a,b : 2つのデータ(参照) '
      25		'''''''''''''''''''''''''''''''''''
      26		Sub swap (ByRef a As Integer, ByRef b As Integer)
      27			Dim temp As Integer = a
      28			a = b
      29			b = temp
      30		End Sub
      31	
      32		'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
      33		' バブルソート                                                  '
      34		'      n : データの数                                           '
      35		'      data : データ                                            '
      36		'      compare : 比較を行う関数                                 '
      37		' バブルソートの手順                                            '
      38		'     1)配列data(i)にn個のデータが入っているものとする.   '
      39		'        i=0,1,・・・,n-1                                  '
      40		'     2)i番目のデータとi+1番目のデータを比較し,もし,     '
      41		'        data(i+1) < data(i) (昇順の場合)            '
      42		'      であればそれらのデータを交換する. i=0,1,・・・,n-2  '
      43		'        →この結果,data(n-1)に最も大きなデータが入る  '
      44		'              ことになる                                       '
      45		'     3)次に,n-1個のデータに対し上の処理を繰り返す.      '
      46		'     4)同様に,n-2,n-3,・・・個のデータに対して同じ処理 '
      47		'        を繰り返す                                             '
      48		'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
      49		Sub func6(n As Integer, data() As Integer,
      50		          compare As Func(Of Integer, Integer, Boolean))
      51			Dim sw As Integer = 0
      52		
      53			If n > 1 Then
      54				For i1 As Integer = 0 To n-2
      55					If compare(data(i1), data(i1+1)) Then
      56						sw = 1
      57						swap(data(i1), data(i1+1))
      58					End If
      59				Next
      60			End If
      61		
      62			If sw > 0 Then
      63				func6(n-1, data, compare)
      64			End If
      65		End Sub
      66	End Module
      				
        バブルソートを行う関数 func6 に,データの数( 5 ),ソートすべきデータ( a7 or a8 ),及び,比較を実行する内容をラムダ式で記述して送っています.また,関数側では,Func を使用しています( 50 行目).このプログラム内の出力文によって,以下に示すような結果が得られます.正しくソートが行われているのが分かると思います.なお,08 行目~ 15 行目の代わりに,16 行目~ 17 行目の記述でも構いません.
      関数名(sort)
         前 3 2 5 4 1
         前 3 2 5 4 1
         後 1 2 3 4 5
         後 5 4 3 2 1					
    6. 関数名(ニュートン法)
      01	Module Test
      02		Sub Main()
      03			Console.WriteLine("関数名(Newton 法)")
      04			Dim eps1 As Double = 1.0e-7
      05			Dim eps2 As Double = 1.0e-10
      06			Dim x0 As Double   = 0.0
      07			Dim max As Integer = 20
      08			Dim ind As Integer = 0
      09			Dim x As Double = func7(x0, eps1, eps2, max, ind,
      10			                        Function(v1) Math.Exp(v1) - 3.0 * v1,
      11			                        Function(v2) Math.Exp(v2) - 3.0)
      12			Console.WriteLine("   回数=" & ind & " x=" & x & " 関数値=" &
      13			                  (Math.Exp(x) - 3.0 * x) & " 微係数=" & (Math.Exp(x) - 3.0))
      14		End Sub
      15		
      16		'''''''''''''''''''''''''''''''''''''''''''''''''''''
      17		' Newton法による非線形方程式(f(x)=0)の解            '
      18		'      x0 : 初期値                                  '
      19		'      eps1 : 終了条件1(|x(k+1)-x(k)|<eps1)   '
      20		'      eps2 : 終了条件2(|f(x(k))|<eps2)       '
      21		'      max : 最大試行回数                           '
      22		'      ind : 実際の試行回数(参照)                 '
      23		'            (負の時は解を得ることができなかった) '
      24		'      fn : f(x)を計算する関数名                    '
      25		'      dfn : f(x)の微分を計算する関数名             '
      26		'      return : 解                                  '
      27		'''''''''''''''''''''''''''''''''''''''''''''''''''''
      28		Function func7(x0 As Double, eps1 As Double, eps2 As Double, max As Integer,
      29		               ByRef ind As Integer,
      30		               fn As Func(Of Double, Double), dfn As Func(Of Double, Double))
      31			Dim x As Double   = x0
      32			Dim x1 As Double  = x0
      33			Dim sw As Integer = 0
      34			ind = 0
      35		
      36			Do While sw = 0 And ind >= 0
      37				sw   = 1
      38				ind += 1
      39				Dim g As Double = fn(x1)
      40				If Math.Abs(g) > eps2 Then
      41					If ind <= max Then
      42						Dim dg As Double = dfn(x1)
      43						If Math.Abs(dg) > eps2 Then
      44							x = x1 - g / dg
      45							If Math.Abs(x-x1) > eps1 And Math.Abs(x-x1) > eps1*Math.Abs(x) Then
      46								x1 = x
      47								sw = 0
      48							End If
      49						Else
      50							ind = -1
      51						End If
      52					Else
      53						ind = -1
      54					End If
      55				End If
      56			Loop
      57		
      58			Return x
      59		End Function
      60	End Module
      				
        上と同様,ラムダ式を関数の引数とした場合の例です.この例においては,ニュートン法によって非線形方程式 f(x) = ex - 3x = 0 の解を求めています.解を求めるための関数 func7 に,初期値( x0 ),収束判定のための閾値( eps1,eps2 ),最大試行回数( max ),収束までの実行回数を返す変数( ind ),関数値を計算するための処理( snx ),関数の微分値を計算するための処理( dsnx )を引数として渡しています.このプログラム内の出力文によって,以下に示すような結果が得られます.
      関数名(Newton 法)
         回数=5 x=0.619061286735945 関数値=-2.22044604925031E-16 微係数=-1.14281613979216					

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