さまざまな言語で数値計算
Only Do What Only You Can Do
スプライン補間
複数の点が与えられているとき, これらを1つの多項式でつなげるのではなく, 2点ずつの区間に分けて, それぞれの区間ごとに別々の3次式を設定する.
まず, 連立1次方程式をたてる.
その連立1次方程式を解いて $ s_i $ を求める.
区間 $ x_i $ ~ $ x_{i+1} $ の3次式は, 得られた $ s_i $ を使って, 次のように表すことができる.
この式を使って, 与えられた点以外の点の値を求める.
例題として,
を近似する.
VBScript
Option Explicit 'データ点の数 - 1 Private Const N = 6 Dim x(): ReDim x(N) Dim y(): ReDim y(N) '1.5刻みで -4.5~4.5 まで, 7点だけ値をセット Dim i For i = 0 To N Dim d1: d1 = i * 1.5 - 4.5 x(i) = d1 y(i) = f(d1) Next '3項方程式の係数の表を作る Dim a(): ReDim a(N) Dim b(): ReDim b(N) Dim c(): ReDim c(N) Dim d(): ReDim d(N) For i = 1 To N - 1 a(i) = x(i) - x(i-1) b(i) = 2.0 * (x(i+1) - x(i-1)) c(i) = x(i+1) - x(i) d(i) = 6.0 * ((y(i+1) - y(i)) / (x(i+1) - x(i)) - (y(i) - y(i-1)) / (x(i) - x(i-1))) Next '3項方程式を解く (ト-マス法) Dim g(): ReDim g(N) Dim s(): ReDim s(N) g(1) = b(1) s(1) = d(1) For i = 2 To N - 1 g(i) = b(i) - a(i) * c(i-1) / g(i-1) s(i) = d(i) - a(i) * s(i-1) / g(i-1) Next Dim z(): ReDim z(N) z(0) = 0 z(N) = 0 z(N-1) = s(N-1) / g(N-1) For i = N - 2 To 1 Step -1 z(i) = (s(i) - c(i) * z(i+1)) / g(i) Next '0.5刻みで 与えられていない値を補間 For i = 0 To 18 d1 = i * 0.5 - 4.5 Dim d2: d2 = f(d1) Dim d3: d3 = spline(d1, x, y, z) '元の関数と比較 WScript.StdOut.Write Right(Space(5) & FormatNumber(d1, 2, -1, 0, 0), 5) & vbTab WScript.StdOut.Write Right(Space(8) & FormatNumber(d2, 5, -1, 0, 0), 8) & vbTab WScript.StdOut.Write Right(Space(8) & FormatNumber(d3, 5, -1, 0, 0), 8) & vbTab WScript.StdOut.WriteLine Right(Space(8) & FormatNumber(d2 - d3, 5, -1, 0, 0), 8) Next '元の関数 Private Function f(ByVal x) f = x - (x ^ 3) / (3 * 2) + (x ^ 5) / (5 * 4 * 3 * 2) End Function 'Spline (スプライン) 補間 Private Function spline(ByVal d, ByVal x(), ByVal y(), ByVal z()) '補間関数値がどの区間にあるか Dim k: k = -1 Dim i For i = 1 To N If d <= x(i) Then k = i - 1 Exit For End If Next If k < 0 Then k = N Dim d1: d1 = x(k+1) - d Dim d2: d2 = d - x(k) Dim d3: d3 = x(k+1) - x(k) spline = (z(k) * (d1 ^ 3) + z(k+1) * (d2 ^ 3)) / (6.0 * d3) + _ (y(k) / d3 - z(k) * d3 / 6.0) * d1 + _ (y(k+1) / d3 - z(k+1) * d3 / 6.0) * d2 End Function
Z:\>cscript //nologo Z:\0705.vbs -4.50 -4.68984 -4.68984 0.00000 -4.00 -1.86667 -2.90573 1.03906 -3.50 -0.73099 -1.41849 0.68750 -3.00 -0.52500 -0.52500 0.00000 -2.50 -0.70964 -0.39714 -0.31250 -2.00 -0.93333 -0.70677 -0.22656 -1.50 -1.00078 -1.00078 -0.00000 -1.00 -0.84167 -0.92760 0.08594 -0.50 -0.47943 -0.54193 0.06250 0.00 0.00000 0.00000 0.00000 0.50 0.47943 0.54193 -0.06250 1.00 0.84167 0.92760 -0.08594 1.50 1.00078 1.00078 0.00000 2.00 0.93333 0.70677 0.22656 2.50 0.70964 0.39714 0.31250 3.00 0.52500 0.52500 -0.00000 3.50 0.73099 1.41849 -0.68750 4.00 1.86667 2.90573 -1.03906 4.50 4.68984 4.68984 0.00000
JScript
// データ点の数 var N = 7 var x = [] var y = [] // 1.5刻みで -4.5~4.5 まで, 7点だけ値をセット for (var i = 0; i < N; i++) { var d1 = i * 1.5 - 4.5 x[i] = d1 y[i] = f(d1) } // 3項方程式の係数の表を作る var a = [] var b = [] var c = [] var d = [] for (var i = 1; i < N - 1; i++) { a[i] = x[i] - x[i-1] b[i] = 2.0 * (x[i+1] - x[i-1]) c[i] = x[i+1] - x[i] d[i] = 6.0 * ((y[i+1] - y[i]) / (x[i+1] - x[i]) - (y[i] - y[i-1]) / (x[i] - x[i-1])) } // 3項方程式を解く (ト-マス法) var g = [] var s = [] g[1] = b[1] s[1] = d[1] for (var i = 2; i < N - 1; i++) { g[i] = b[i] - a[i] * c[i-1] / g[i-1] s[i] = d[i] - a[i] * s[i-1] / g[i-1] } var z = [] z[0] = 0 z[N-1] = 0 z[N-2] = s[N-2] / g[N-2] for (var i = N - 3; i >= 1; i--) z[i] = (s[i] - c[i] * z[i+1]) / g[i] // 0.5刻みで 与えられていない値を補間 for (var i = 0; i <= 18; i++) { var d1 = i * 0.5 - 4.5 var d2 = f(d1) var d3 = spline(d1, x, y, z) // 元の関数と比較 WScript.StdOut.Write((" " + d1.toFixed(2) ).slice(-5) + "\t") WScript.StdOut.Write((" " + d2.toFixed(5) ).slice(-8) + "\t") WScript.StdOut.Write((" " + d3.toFixed(5) ).slice(-8) + "\t") WScript.StdOut.Write((" " + (d2 - d3).toFixed(5)).slice(-8) + "\n") } // 元の関数 function f(x) { return x - Math.pow(x,3) / (3 * 2) + Math.pow(x,5) / (5 * 4 * 3 * 2) } // Spline (スプライン) 補間 function spline(d, x, y, z) { // 補間関数値がどの区間にあるか var k = -1 for (var i = 1; i < N; i++) { if (d <= x[i]) { k = i - 1 break } } if (k < 0) k = N - 1 var d1 = x[k+1] - d var d2 = d - x[k] var d3 = x[k+1] - x[k] return (z[k] * Math.pow(d1,3) + z[k+1] * Math.pow(d2,3)) / (6.0 * d3) + (y[k] / d3 - z[k] * d3 / 6.0) * d1 + (y[k+1] / d3 - z[k+1] * d3 / 6.0) * d2 }
Z:\>cscript //nologo Z:\0705.js -4.50 -4.68984 -4.68984 0.00000 -4.00 -1.86667 -2.90573 1.03906 -3.50 -0.73099 -1.41849 0.68750 -3.00 -0.52500 -0.52500 0.00000 -2.50 -0.70964 -0.39714 -0.31250 -2.00 -0.93333 -0.70677 -0.22656 -1.50 -1.00078 -1.00078 -0.00000 -1.00 -0.84167 -0.92760 0.08594 -0.50 -0.47943 -0.54193 0.06250 0.00 0.00000 0.00000 0.00000 0.50 0.47943 0.54193 -0.06250 1.00 0.84167 0.92760 -0.08594 1.50 1.00078 1.00078 0.00000 2.00 0.93333 0.70677 0.22656 2.50 0.70964 0.39714 0.31250 3.00 0.52500 0.52500 -0.00000 3.50 0.73099 1.41849 -0.68750 4.00 1.86667 2.90573 -1.03906 4.50 4.68984 4.68984 0.00000
PowerShell
# データ点の数 set-variable -option constant -name N -value 7 # 元の関数 function f($x) { $x - [Math]::Pow($x, 3) / (3 * 2) + [Math]::Pow($x, 5) / (5 * 4 * 3 * 2) } # Spline (スプライン) 補間 function spline($d, $x, $y, $z) { # 補間関数値がどの区間にあるか $k = -1 foreach ($i in 1..($N - 1)) { if ($d -le $x[$i]) { $k = $i - 1 break } } if ($k -lt 0) { $k = $N - 1 } $d1 = $x[($k+1)] - $d $d2 = $d - $x[$k] $d3 = $x[($k+1)] - $x[$k] ($z[$k] * [Math]::Pow($d1,3) + $z[($k+1)] * [Math]::Pow($d2,3)) / (6.0 * $d3) + ($y[$k] / $d3 - $z[$k] * $d3 / 6.0) * $d1 + ($y[($k+1)] / $d3 - $z[($k+1)] * $d3 / 6.0) * $d2 } $x = New-Object double[] $N $y = New-Object double[] $N # 1.5刻みで -4.5~4.5 まで, 7点だけ値をセット foreach ($i in 0..($N - 1)) { $d1 = $i * 1.5 - 4.5 $x[$i] = $d1 $y[$i] = f($d1) } # 3項方程式の係数の表を作る $a = New-Object double[] $N $b = New-Object double[] $N $c = New-Object double[] $N $d = New-Object double[] $N foreach ($i in 1..($N - 2)) { $a[$i] = $x[$i] - $x[($i-1)] $b[$i] = 2.0 * ($x[($i+1)] - $x[($i-1)]) $c[$i] = $x[($i+1)] - $x[$i] $d[$i] = 6.0 * (($y[($i+1)] - $y[$i]) / ($x[($i+1)] - $x[$i]) - ($y[$i] - $y[($i-1)]) / ($x[$i] - $x[($i-1)])) } # 3項方程式を解く (ト-マス法) $g = New-Object double[] $N $s = New-Object double[] $N $g[1] = $b[1] $s[1] = $d[1] foreach ($i in 2..($N - 2)) { $g[$i] = $b[$i] - $a[$i] * $c[($i-1)] / $g[($i-1)] $s[$i] = $d[$i] - $a[$i] * $s[($i-1)] / $g[($i-1)] } $z = New-Object double[] $N $z[0] = 0 $z[($N-1)] = 0 $z[($N-2)] = $s[($N-2)] / $g[($N-2)] for ($i = $N - 3; $i -ge 1; $i--) { $z[$i] = ($s[$i] - $c[$i] * $z[($i+1)]) / $g[$i] } # 0.5刻みで 与えられていない値を補間 foreach ($i in 0..18) { $d1 = $i * 0.5 - 4.5 $d2 = f($d1) $d3 = (spline $d1 $x $y $z) # 元の関数と比較 Write-Host ([String]::Format("{0,5:F2}`t{1,8:F5}`t{2,8:F5}`t{3,8:F5}", $d1, $d2, $d3, ($d2 - $d3))) }
Z:\>powershell -file Z:\0705.ps1 -4.50 -4.68984 -4.68984 0.00000 -4.00 -1.86667 -2.90573 1.03906 -3.50 -0.73099 -1.41849 0.68750 -3.00 -0.52500 -0.52500 0.00000 -2.50 -0.70964 -0.39714 -0.31250 -2.00 -0.93333 -0.70677 -0.22656 -1.50 -1.00078 -1.00078 0.00000 -1.00 -0.84167 -0.92760 0.08594 -0.50 -0.47943 -0.54193 0.06250 0.00 0.00000 0.00000 0.00000 0.50 0.47943 0.54193 -0.06250 1.00 0.84167 0.92760 -0.08594 1.50 1.00078 1.00078 0.00000 2.00 0.93333 0.70677 0.22656 2.50 0.70964 0.39714 0.31250 3.00 0.52500 0.52500 0.00000 3.50 0.73099 1.41849 -0.68750 4.00 1.86667 2.90573 -1.03906 4.50 4.68984 4.68984 0.00000
Perl
# データ点の数 - 1 use constant N => 6; my @x = (); my @y = (); # 1.5刻みで -4.5~4.5 まで, 7点だけ値をセット for $i (0..N) { my $d1 = $i * 1.5 - 4.5; $x[$i] = $d1; $y[$i] = f($d1); } # 3項方程式の係数の表を作る my @a = (); my @b = (); my @c = (); my @d = (); for $i (1..(N - 1)) { $a[$i] = $x[$i] - $x[$i-1]; $b[$i] = 2.0 * ($x[$i+1] - $x[$i-1]); $c[$i] = $x[$i+1] - $x[$i]; $d[$i] = 6.0 * (($y[$i+1] - $y[$i]) / ($x[$i+1] - $x[$i]) - ($y[$i] - $y[$i-1]) / ($x[$i] - $x[$i-1])); } # 3項方程式を解く (ト-マス法) my @g = (); my @s = (); $g[1] = $b[1]; $s[1] = $d[1]; for $i (2..(N - 1)) { $g[$i] = $b[$i] - $a[$i] * $c[$i-1] / $g[$i-1]; $s[$i] = $d[$i] - $a[$i] * $s[$i-1] / $g[$i-1]; } my @z = (); $z[0] = 0; $z[N] = 0; $z[N-1] = $s[N-1] / $g[N-1]; for ($i = N - 2; $i >= 1; $i--) { $z[$i] = ($s[$i] - $c[$i] * $z[$i+1]) / $g[$i]; } # 0.5刻みで 与えられていない値を補間 for $i (0..18) { my $d1 = $i * 0.5 - 4.5; my $d2 = f($d1); my $d3 = spline($d1, \@x, \@y, \@z); # 元の関数と比較 printf("%5.2f\t%8.5f\t%8.5f\t%8.5f\n", $d1, $d2, $d3, $d2 - $d3); } # 元の関数 sub f { my ($x) = @_; $x - ($x ** 3) / (3 * 2) + ($x ** 5) / (5 * 4 * 3 * 2); } # Spline (スプライン) 補間 sub spline { my ($d, $x, $y, $z) = @_; # 補間関数値がどの区間にあるか my $k = -1; for $i (1..N) { if ($d <= $$x[$i]) { $k = $i - 1; last; } } if ($k < 0) { $k = N; } $d1 = $$x[$k+1] - $d; $d2 = $d - $$x[$k]; $d3 = $$x[$k+1] - $$x[$k]; ($$z[$k] * ($d1 ** 3) + $$z[$k+1] * ($d2 ** 3)) / (6.0 * $d3) + ($$y[$k] / $d3 - $$z[$k] * $d3 / 6.0) * $d1 + ($$y[$k+1] / $d3 - $$z[$k+1] * $d3 / 6.0) * $d2; }
Z:\>perl Z:\0705.pl -4.50 -4.68984 -4.68984 0.00000 -4.00 -1.86667 -2.90573 1.03906 -3.50 -0.73099 -1.41849 0.68750 -3.00 -0.52500 -0.52500 0.00000 -2.50 -0.70964 -0.39714 -0.31250 -2.00 -0.93333 -0.70677 -0.22656 -1.50 -1.00078 -1.00078 -0.00000 -1.00 -0.84167 -0.92760 0.08594 -0.50 -0.47943 -0.54193 0.06250 0.00 0.00000 0.00000 0.00000 0.50 0.47943 0.54193 -0.06250 1.00 0.84167 0.92760 -0.08594 1.50 1.00078 1.00078 0.00000 2.00 0.93333 0.70677 0.22656 2.50 0.70964 0.39714 0.31250 3.00 0.52500 0.52500 -0.00000 3.50 0.73099 1.41849 -0.68750 4.00 1.86667 2.90573 -1.03906 4.50 4.68984 4.68984 0.00000
PHP
<?php # データ点の数 - 1 define("N", 6); $x = array(); $y = array(); # 1.5刻みで -4.5~4.5 まで, 7点だけ値をセット foreach (range(0, N) as $i) { $d1 = $i * 1.5 - 4.5; $x[$i] = $d1; $y[$i] = f($d1); } # 3項方程式の係数の表を作る $a = array(); $b = array(); $c = array(); $d = array(); foreach (range(1, N - 1) as $i) { $a[$i] = $x[$i] - $x[$i-1]; $b[$i] = 2.0 * ($x[$i+1] - $x[$i-1]); $c[$i] = $x[$i+1] - $x[$i]; $d[$i] = 6.0 * (($y[$i+1] - $y[$i]) / ($x[$i+1] - $x[$i]) - ($y[$i] - $y[$i-1]) / ($x[$i] - $x[$i-1])); } # 3項方程式を解く (ト-マス法) $g = array(); $s = array(); $g[1] = $b[1]; $s[1] = $d[1]; foreach (range(2, N - 1) as $i) { $g[$i] = $b[$i] - $a[$i] * $c[$i-1] / $g[$i-1]; $s[$i] = $d[$i] - $a[$i] * $s[$i-1] / $g[$i-1]; } $z = array(); $z[0] = 0; $z[N] = 0; $z[N-1] = $s[N-1] / $g[N-1]; for ($i = N - 2; $i >= 1; $i--) { $z[$i] = ($s[$i] - $c[$i] * $z[$i+1]) / $g[$i]; } # 0.5刻みで 与えられていない値を補間 foreach (range(0, 18) as $i) { $d1 = $i * 0.5 - 4.5; $d2 = f($d1); $d3 = spline($d1, $x, $y, $z); # 元の関数と比較 printf("%5.2f\t%8.5f\t%8.5f\t%8.5f\n", $d1, $d2, $d3, $d2 - $d3); } # 元の関数 function f($x) { return $x - pow($x, 3) / (3 * 2) + pow($x, 5) / (5 * 4 * 3 * 2); } # Spline (スプライン) 補間 function spline($d, $x, $y, $z) { # 補間関数値がどの区間にあるか $k = -1; foreach (range(1, N) as $i) { if ($d <= $x[$i]) { $k = $i - 1; break; } } if ($k < 0) $k = N; $d1 = $x[$k+1] - $d; $d2 = $d - $x[$k]; $d3 = $x[$k+1] - $x[$k]; return ($z[$k] * pow($d1, 3) + $z[$k+1] * pow($d2, 3)) / (6.0 * $d3) + ($y[$k] / $d3 - $z[$k] * $d3 / 6.0) * $d1 + ($y[$k+1] / $d3 - $z[$k+1] * $d3 / 6.0) * $d2; } ?>
Z:\>php Z:\0705.php -4.50 -4.68984 -4.68984 0.00000 -4.00 -1.86667 -2.90573 1.03906 -3.50 -0.73099 -1.41849 0.68750 -3.00 -0.52500 -0.52500 0.00000 -2.50 -0.70964 -0.39714 -0.31250 -2.00 -0.93333 -0.70677 -0.22656 -1.50 -1.00078 -1.00078 -0.00000 -1.00 -0.84167 -0.92760 0.08594 -0.50 -0.47943 -0.54193 0.06250 0.00 0.00000 0.00000 0.00000 0.50 0.47943 0.54193 -0.06250 1.00 0.84167 0.92760 -0.08594 1.50 1.00078 1.00078 0.00000 2.00 0.93333 0.70677 0.22656 2.50 0.70964 0.39714 0.31250 3.00 0.52500 0.52500 -0.00000 3.50 0.73099 1.41849 -0.68750 4.00 1.86667 2.90573 -1.03906 4.50 4.68984 4.68984 0.00000
Python
# coding: Shift_JIS # データ点の数 N = 7 # 元の関数 def f(x): return x - (x ** 3) / (3 * 2) + (x ** 5) / (5 * 4 * 3 * 2) # Spline (スプライン) 補間 def spline(d, x, y, z): # 補間関数値がどの区間にあるか k = -1 for i in range(1, N): if d <= x[i]: k = i - 1 break if (k < 0): k = N - 1 d1 = x[k+1] - d d2 = d - x[k] d3 = x[k+1] - x[k] return ( (z[k] * (d1 ** 3) + z[k+1] * (d2 ** 3)) / (6.0 * d3) + (y[k] / d3 - z[k] * d3 / 6.0) * d1 + (y[k+1] / d3 - z[k+1] * d3 / 6.0) * d2) x = [0 for i in range(N)] y = [0 for i in range(N)] # 1.5刻みで -4.5~4.5 まで, 7点だけ値をセット for i in range(0, N): d = i * 1.5 - 4.5 x[i] = d y[i] = f(d) # 3項方程式の係数の表を作る a = [0 for i in range(N)] b = [0 for i in range(N)] c = [0 for i in range(N)] d = [0 for i in range(N)] for i in range(1, N - 1): a[i] = x[i] - x[i-1] b[i] = 2.0 * (x[i+1] - x[i-1]) c[i] = x[i+1] - x[i] d[i] = 6.0 * ((y[i+1] - y[i]) / (x[i+1] - x[i]) - (y[i] - y[i-1]) / (x[i] - x[i-1])) # 3項方程式を解く (ト-マス法) g = [0 for i in range(N)] s = [0 for i in range(N)] g[1] = b[1] s[1] = d[1] for i in range(2, N - 1): g[i] = b[i] - a[i] * c[i-1] / g[i-1] s[i] = d[i] - a[i] * s[i-1] / g[i-1] z = [0 for i in range(N)] z[0] = 0 z[N-1] = 0 z[N-2] = s[N-2] / g[N-2] i = N - 3 while i >= 1: z[i] = (s[i] - c[i] * z[i+1]) / g[i] i -= 1 # 0.5刻みで 与えられていない値を補間 for i in range(0, 19): d1 = i * 0.5 - 4.5 d2 = f(d1) d3 = spline(d1, x, y, z) # 元の関数と比較 print "%5.2f\t%8.5f\t%8.5f\t%8.5f" % (d1, d2, d3, d2 - d3)
Z:\>python Z:\0705.py -4.50 -4.68984 -4.68984 0.00000 -4.00 -1.86667 -2.90573 1.03906 -3.50 -0.73099 -1.41849 0.68750 -3.00 -0.52500 -0.52500 0.00000 -2.50 -0.70964 -0.39714 -0.31250 -2.00 -0.93333 -0.70677 -0.22656 -1.50 -1.00078 -1.00078 -0.00000 -1.00 -0.84167 -0.92760 0.08594 -0.50 -0.47943 -0.54193 0.06250 0.00 0.00000 0.00000 0.00000 0.50 0.47943 0.54193 -0.06250 1.00 0.84167 0.92760 -0.08594 1.50 1.00078 1.00078 0.00000 2.00 0.93333 0.70677 0.22656 2.50 0.70964 0.39714 0.31250 3.00 0.52500 0.52500 -0.00000 3.50 0.73099 1.41849 -0.68750 4.00 1.86667 2.90573 -1.03906 4.50 4.68984 4.68984 0.00000
Ruby
# データ点の数 - 1 N = 6 # 元の関数 def f(x) x - (x ** 3) / (3 * 2) + (x ** 5) / (5 * 4 * 3 * 2) end # Spline (スプライン) 補間 def spline(d, x, y, z) # 補間関数値がどの区間にあるか k = -1 (1..N).each do |i| if d <= x[i] k = i - 1 break end end if k < 0 k = N end d1 = x[k+1] - d d2 = d - x[k] d3 = x[k+1] - x[k] (z[k] * (d1 ** 3) + z[k+1] * (d2 ** 3)) / (6.0 * d3) + (y[k] / d3 - z[k] * d3 / 6.0) * d1 + (y[k+1] / d3 - z[k+1] * d3 / 6.0) * d2 end x = Array.new(N) y = Array.new(N) # 1.5刻みで -4.5~4.5 まで, 7点だけ値をセット (0..N).each do |i| d = i * 1.5 - 4.5 x[i] = d y[i] = f(d) end # 3項方程式の係数の表を作る a = Array.new(N) b = Array.new(N) c = Array.new(N) d = Array.new(N) (1..(N - 1)).each do |i| a[i] = x[i] - x[i-1] b[i] = 2.0 * (x[i+1] - x[i-1]) c[i] = x[i+1] - x[i] d[i] = 6.0 * ((y[i+1] - y[i]) / (x[i+1] - x[i]) - (y[i] - y[i-1]) / (x[i] - x[i-1])) end # 3項方程式を解く (ト-マス法) g = Array.new(N) s = Array.new(N) g[1] = b[1] s[1] = d[1] (2..(N - 1)).each do |i| g[i] = b[i] - a[i] * c[i-1] / g[i-1] s[i] = d[i] - a[i] * s[i-1] / g[i-1] end z = Array.new(N) z[0] = 0 z[N] = 0 z[N-1] = s[N-1] / g[N-1] i = N - 2 while i > 0 do z[i] = (s[i] - c[i] * z[i+1]) / g[i] i -= 1 end # 0.5刻みで 与えられていない値を補間 (0..18).each do |i| d1 = i * 0.5 - 4.5 d2 = f(d1) d3 = spline(d1, x, y, z) # 元の関数と比較 printf("%5.2f\t%8.5f\t%8.5f\t%8.5f\n", d1, d2, d3, d2 - d3) end
Z:\>ruby Z:\0705.rb -4.50 -4.68984 -4.68984 0.00000 -4.00 -1.86667 -2.90573 1.03906 -3.50 -0.73099 -1.41849 0.68750 -3.00 -0.52500 -0.52500 0.00000 -2.50 -0.70964 -0.39714 -0.31250 -2.00 -0.93333 -0.70677 -0.22656 -1.50 -1.00078 -1.00078 -0.00000 -1.00 -0.84167 -0.92760 0.08594 -0.50 -0.47943 -0.54193 0.06250 0.00 0.00000 0.00000 0.00000 0.50 0.47943 0.54193 -0.06250 1.00 0.84167 0.92760 -0.08594 1.50 1.00078 1.00078 0.00000 2.00 0.93333 0.70677 0.22656 2.50 0.70964 0.39714 0.31250 3.00 0.52500 0.52500 -0.00000 3.50 0.73099 1.41849 -0.68750 4.00 1.86667 2.90573 -1.03906 4.50 4.68984 4.68984 0.00000
Groovy
Pascal
program Pas0705(arg); {$MODE delphi} uses SysUtils, Math; const // データ点の数 - 1 N = 6; // 元の関数 function f(x:Double):Double; begin result := x - power(x,3) / (3 * 2) + power(x,5) / (5 * 4 * 3 * 2); end; // Spline (スプライン) 補間 function spline(d:Double; x:array of Double; y:array of Double; z:array of Double):Double; var d1, d2, d3 :Double; i, k :Integer; begin // 補間関数値がどの区間にあるか k := -1; for i := 1 to High(x) do begin if d <= x[i] then begin k := i - 1; break; end; end; if k < 0 then k := i - 1; d1 := x[k+1] - d; d2 := d - x[k]; d3 := x[k+1] - x[k]; result := (z[k] * power(d1,3) + z[k+1] * power(d2,3)) / (6.0 * d3) + (y[k] / d3 - z[k] * d3 / 6.0) * d1 + (y[k+1] / d3 - z[k+1] * d3 / 6.0) * d2; end; var i, j :Integer; x :array [0..N] of Double; y :array [0..N] of Double; a :array [0..N] of Double; b :array [0..N] of Double; c :array [0..N] of Double; d :array [0..N] of Double; g :array [0..N] of Double; s :array [0..N] of Double; z :array [0..N] of Double; d1, d2, d3 :Double; begin // 1.5刻みで -4.5~4.5 まで, 7点だけ値をセット for i := Low(x) to High(x) do begin d1 := i * 1.5 - 4.5; x[i] := d1; y[i] := f(d1); end; // 3項方程式の係数の表を作る for i := 1 to High(x)-1 do begin a[i] := x[i] - x[i-1]; b[i] := 2.0 * (x[i+1] - x[i-1]); c[i] := x[i+1] - x[i]; d[i] := 6.0 * ((y[i+1] - y[i]) / (x[i+1] - x[i]) - (y[i] - y[i-1]) / (x[i] - x[i-1])); end; // 3項方程式を解く (ト-マス法) g[1] := b[1]; s[1] := d[1]; for i := 2 to High(a)-1 do begin g[i] := b[i] - a[i] * c[i-1] / g[i-1]; s[i] := d[i] - a[i] * s[i-1] / g[i-1]; end; z[0] := 0; z[N] := 0; z[N-1] := s[N-1] / g[N-1]; for i := N-2 downto 1 do begin z[i] := (s[i] - c[i] * z[i+1]) / g[i]; end; // 0.5刻みで 与えられていない値を補間 for i := 0 to 18 do begin d1 := i * 0.5 - 4.5; d2 := f(d1); d3 := spline(d1, x, y, z); // 元の関数と比較 writeln(format('%5.2f'#9'%8.5f'#9'%8.5f'#9'%8.5f', [d1, d2, d3, d2 - d3])); end; end.
Z:\>fpc -v0 -l- Pas0705.pp Z:\>Pas0705 -4.50 -4.68984 -4.68984 0.00000 -4.00 -1.86667 -2.90573 1.03906 -3.50 -0.73099 -1.41849 0.68750 -3.00 -0.52500 -0.52500 0.00000 -2.50 -0.70964 -0.39714 -0.31250 -2.00 -0.93333 -0.70677 -0.22656 -1.50 -1.00078 -1.00078 0.00000 -1.00 -0.84167 -0.92760 0.08594 -0.50 -0.47943 -0.54193 0.06250 0.00 0.00000 0.00000 0.00000 0.50 0.47943 0.54193 -0.06250 1.00 0.84167 0.92760 -0.08594 1.50 1.00078 1.00078 0.00000 2.00 0.93333 0.70677 0.22656 2.50 0.70964 0.39714 0.31250 3.00 0.52500 0.52500 0.00000 3.50 0.73099 1.41849 -0.68750 4.00 1.86667 2.90573 -1.03906 4.50 4.68984 4.68984 0.00000
Ada
with TEXT_IO, Ada.Long_Float_Text_IO; use TEXT_IO, Ada.Long_Float_Text_IO; procedure Ada0705 is -- データ点の数 - 1 N : Constant Integer := 6; type Long_Float_Array is array (0..N) of Long_Float; x : Long_Float_Array; y : Long_Float_Array; a : Long_Float_Array; b : Long_Float_Array; c : Long_Float_Array; d : Long_Float_Array; g : Long_Float_Array; s : Long_Float_Array; z : Long_Float_Array; d1, d2, d3 : Long_Float; k : Integer; -- 元の関数 function f(x:Long_Float) return Long_Float is begin return x - Long_Float(x ** 3) / Long_Float(3 * 2) + Long_Float(x ** 5) / Long_Float(5 * 4 * 3 * 2); end f; -- Spline (スプライン) 補間 function spline(d:Long_Float; x:Long_Float_Array; y:Long_Float_Array; z:Long_Float_Array) return Long_Float is d1, d2, d3 : Long_Float; k : Integer; begin -- 補間関数値がどの区間にあるか k := -1; for i in 1 .. x'Last loop if d <= x(i) then k := i - 1; exit; end if; end loop; if k < 0 then k := N; end if; d1 := x(k+1) - d; d2 := d - x(k); d3 := x(k+1) - x(k); return (z(k) * (d1 ** 3) + z(k+1) * (d2 ** 3)) / (6.0 * d3) + (y(k) / d3 - z(k) * d3 / 6.0) * d1 + (y(k+1) / d3 - z(k+1) * d3 / 6.0) * d2; end; begin -- 1.5刻みで -4.5~4.5 まで, 7点だけ値をセット for i in x'Range loop d1 := Long_Float(i) * 1.5 - 4.5; x(i) := d1; y(i) := f(d1); end loop; -- 3項方程式の係数の表を作る for i in 1..x'Last-1 loop a(i) := x(i) - x(i-1); b(i) := 2.0 * (x(i+1) - x(i-1)); c(i) := x(i+1) - x(i); d(i) := 6.0 * ((y(i+1) - y(i)) / (x(i+1) - x(i)) - (y(i) - y(i-1)) / (x(i) - x(i-1))); end loop; -- 3項方程式を解く (ト-マス法) g(1) := b(1); s(1) := d(1); for i in 2..a'Last-1 loop g(i) := b(i) - a(i) * c(i-1) / g(i-1); s(i) := d(i) - a(i) * s(i-1) / g(i-1); end loop; z(0) := 0.0; z(N) := 0.0; z(N-1) := s(N-1) / g(N-1); k := N - 2; while k > 0 loop z(k) := (s(k) - c(k) * z(k+1)) / g(k); k := k - 1; end loop; -- 0.5刻みで 与えられていない値を補間 for i in 0..18 loop d1 := Long_Float(i) * 0.5 - 4.5; d2 := f(d1); d3 := spline(d1, x, y, z); -- 元の関数と比較 Put(d1, Fore=>2, Aft=>2, Exp=>0); Put(Ascii.HT); Put(d2, Fore=>3, Aft=>5, Exp=>0); Put(Ascii.HT); Put(d3, Fore=>3, Aft=>5, Exp=>0); Put(Ascii.HT); Put(d2 - d3, Fore=>3, Aft=>5, Exp=>0); New_Line; end loop; end Ada0705;
xxxxxx@yyyyyy /Z $ gnatmake Ada0705.adb xxxxxx@yyyyyy /Z $ Ada0705 -4.50 -4.68984 -4.68984 0.00000 -4.00 -1.86667 -2.90573 1.03906 -3.50 -0.73099 -1.41849 0.68750 -3.00 -0.52500 -0.52500 0.00000 -2.50 -0.70964 -0.39714 -0.31250 -2.00 -0.93333 -0.70677 -0.22656 -1.50 -1.00078 -1.00078 0.00000 -1.00 -0.84167 -0.92760 0.08594 -0.50 -0.47943 -0.54193 0.06250 0.00 0.00000 0.00000 0.00000 0.50 0.47943 0.54193 -0.06250 1.00 0.84167 0.92760 -0.08594 1.50 1.00078 1.00078 0.00000 2.00 0.93333 0.70677 0.22656 2.50 0.70964 0.39714 0.31250 3.00 0.52500 0.52500 0.00000 3.50 0.73099 1.41849 -0.68750 4.00 1.86667 2.90573 -1.03906 4.50 4.68984 4.68984 0.00000
VB.NET
Module VB0705 'データ点の数 - 1 Private Const N As Integer = 6 Public Sub Main() Dim x(N) As Double Dim y(N) As Double '1.5刻みで -4.5~4.5 まで, 7点だけ値をセット For i As Integer = 0 To N Dim d1 As Double = i * 1.5 - 4.5 x(i) = d1 y(i) = f(d1) Next '3項方程式の係数の表を作る Dim a(N) As Double Dim b(N) As Double Dim c(N) As Double Dim d(N) As Double For i As Integer = 1 To N - 1 a(i) = x(i) - x(i-1) b(i) = 2.0 * (x(i+1) - x(i-1)) c(i) = x(i+1) - x(i) d(i) = 6.0 * ((y(i+1) - y(i)) / (x(i+1) - x(i)) - (y(i) - y(i-1)) / (x(i) - x(i-1))) Next '3項方程式を解く (ト-マス法) Dim g(N) As Double Dim s(N) As Double g(1) = b(1) s(1) = d(1) For i As Integer = 2 To N - 1 g(i) = b(i) - a(i) * c(i-1) / g(i-1) s(i) = d(i) - a(i) * s(i-1) / g(i-1) Next Dim z(N) As Double z(0) = 0 z(N) = 0 z(N-1) = s(N-1) / g(N-1) For i As Integer = N - 2 To 1 Step -1 z(i) = (s(i) - c(i) * z(i+1)) / g(i) Next '0.5刻みで 与えられていない値を補間 For i As Integer = 0 To 18 Dim d1 As Double = i * 0.5 - 4.5 Dim d2 As Double = f(d1) Dim d3 As Double = spline(d1, x, y, z) '元の関数と比較 Console.WriteLine(String.Format("{0,5:F2}{4}{1,8:F5}{4}{2,8:F5}{4}{3,8:F5}", d1, d2, d3, d2 - d3, vbTab)) Next End Sub '元の関数 Private Function f(ByVal x As Double) As Double Return x - (x ^ 3) / (3 * 2) + (x ^ 5) / (5 * 4 * 3 * 2) End Function 'Spline (スプライン) 補間 Private Function spline(ByVal d As Double, ByVal x() As Double, ByVal y() As Double, ByVal z() As Double) As Double '補間関数値がどの区間にあるか Dim k As Integer = -1 For i As Integer = 1 To N If d <= x(i) Then k = i - 1 Exit For End If Next If (k < 0) Then k = N Dim d1 As Double = x(k+1) - d Dim d2 As Double = d - x(k) Dim d3 As Double = x(k+1) - x(k) Return (z(k) * (d1 ^ 3) + z(k+1) * (d2 ^ 3)) / (6.0 * d3) + (y(k) / d3 - z(k) * d3 / 6.0) * d1 + (y(k+1) / d3 - z(k+1) * d3 / 6.0) * d2 End Function End Module
Z:\>vbc -nologo VB0705.vb Z:\>VB0705 -4.50 -4.68984 -4.68984 0.00000 -4.00 -1.86667 -2.90573 1.03906 -3.50 -0.73099 -1.41849 0.68750 -3.00 -0.52500 -0.52500 0.00000 -2.50 -0.70964 -0.39714 -0.31250 -2.00 -0.93333 -0.70677 -0.22656 -1.50 -1.00078 -1.00078 0.00000 -1.00 -0.84167 -0.92760 0.08594 -0.50 -0.47943 -0.54193 0.06250 0.00 0.00000 0.00000 0.00000 0.50 0.47943 0.54193 -0.06250 1.00 0.84167 0.92760 -0.08594 1.50 1.00078 1.00078 0.00000 2.00 0.93333 0.70677 0.22656 2.50 0.70964 0.39714 0.31250 3.00 0.52500 0.52500 0.00000 3.50 0.73099 1.41849 -0.68750 4.00 1.86667 2.90573 -1.03906 4.50 4.68984 4.68984 0.00000
C#
using System; public class CS0705 { // データ点の数 private const int N = 7; public static void Main() { double[] x = new double[N]; double[] y = new double[N]; // 1.5刻みで -4.5~4.5 まで, 7点だけ値をセット for (int i = 0; i < N; i++) { double d1 = i * 1.5 - 4.5; x[i] = d1; y[i] = f(d1); } // 3項方程式の係数の表を作る double[] a = new double[N]; double[] b = new double[N]; double[] c = new double[N]; double[] d = new double[N]; for (int i = 1; i < N - 1; i++) { a[i] = x[i] - x[i-1]; b[i] = 2.0 * (x[i+1] - x[i-1]); c[i] = x[i+1] - x[i]; d[i] = 6.0 * ((y[i+1] - y[i]) / (x[i+1] - x[i]) - (y[i] - y[i-1]) / (x[i] - x[i-1])); } // 3項方程式を解く (ト-マス法) double[] g = new double[N]; double[] s = new double[N]; g[1] = b[1]; s[1] = d[1]; for (int i = 2; i < N - 1; i++) { g[i] = b[i] - a[i] * c[i-1] / g[i-1]; s[i] = d[i] - a[i] * s[i-1] / g[i-1]; } double[] z = new double[N]; z[0] = 0; z[N-1] = 0; z[N-2] = s[N-2] / g[N-2]; for (int i = N - 3; i >= 1; i--) { z[i] = (s[i] - c[i] * z[i+1]) / g[i]; } // 0.5刻みで 与えられていない値を補間 for (int i = 0; i <= 18; i++) { double d1 = i * 0.5 - 4.5; double d2 = f(d1); double d3 = spline(d1, x, y, z); // 元の関数と比較 Console.WriteLine(string.Format("{0,5:F2}\t{1,8:F5}\t{2,8:F5}\t{3,8:F5}", d1, d2, d3, d2 - d3)); } } // 元の関数 private static double f(double x) { return x - Math.Pow(x,3) / (3 * 2) + Math.Pow(x,5) / (5 * 4 * 3 * 2); } // Spline (スプライン) 補間 private static double spline(double d, double[] x, double[] y, double[] z) { // 補間関数値がどの区間にあるか int k = -1; for (int i = 1; i < N; i++) { if (d <= x[i]) { k = i - 1; break; } } if (k < 0) k = N - 1; double d1 = x[k+1] - d; double d2 = d - x[k]; double d3 = x[k+1] - x[k]; return (z[k] * Math.Pow(d1,3) + z[k+1] * Math.Pow(d2,3)) / (6.0 * d3) + (y[k] / d3 - z[k] * d3 / 6.0) * d1 + (y[k+1] / d3 - z[k+1] * d3 / 6.0) * d2; } }
Z:\>csc -nologo CS0705.cs Z:\>CS0705 -4.50 -4.68984 -4.68984 0.00000 -4.00 -1.86667 -2.90573 1.03906 -3.50 -0.73099 -1.41849 0.68750 -3.00 -0.52500 -0.52500 0.00000 -2.50 -0.70964 -0.39714 -0.31250 -2.00 -0.93333 -0.70677 -0.22656 -1.50 -1.00078 -1.00078 0.00000 -1.00 -0.84167 -0.92760 0.08594 -0.50 -0.47943 -0.54193 0.06250 0.00 0.00000 0.00000 0.00000 0.50 0.47943 0.54193 -0.06250 1.00 0.84167 0.92760 -0.08594 1.50 1.00078 1.00078 0.00000 2.00 0.93333 0.70677 0.22656 2.50 0.70964 0.39714 0.31250 3.00 0.52500 0.52500 0.00000 3.50 0.73099 1.41849 -0.68750 4.00 1.86667 2.90573 -1.03906 4.50 4.68984 4.68984 0.00000
Java
public class Java0705 { // データ点の数 private static final int N = 7; public static void main(String []args) { double[] x = new double[N]; double[] y = new double[N]; // 1.5刻みで -4.5~4.5 まで, 7点だけ値をセット for (int i = 0; i < N; i++) { double d1 = i * 1.5 - 4.5; x[i] = d1; y[i] = f(d1); } // 3項方程式の係数の表を作る double[] a = new double[N]; double[] b = new double[N]; double[] c = new double[N]; double[] d = new double[N]; for (int i = 1; i < N - 1; i++) { a[i] = x[i] - x[i-1]; b[i] = 2.0 * (x[i+1] - x[i-1]); c[i] = x[i+1] - x[i]; d[i] = 6.0 * ((y[i+1] - y[i]) / (x[i+1] - x[i]) - (y[i] - y[i-1]) / (x[i] - x[i-1])); } // 3項方程式を解く (ト-マス法) double[] g = new double[N]; double[] s = new double[N]; g[1] = b[1]; s[1] = d[1]; for (int i = 2; i < N - 1; i++) { g[i] = b[i] - a[i] * c[i-1] / g[i-1]; s[i] = d[i] - a[i] * s[i-1] / g[i-1]; } double[] z = new double[N]; z[0] = 0; z[N-1] = 0; z[N-2] = s[N-2] / g[N-2]; for (int i = N - 3; i >= 1; i--) z[i] = (s[i] - c[i] * z[i+1]) / g[i]; // 0.5刻みで 与えられていない値を補間 for (int i = 0; i <= 18; i++) { double d1 = i * 0.5 - 4.5; double d2 = f(d1); double d3 = spline(d1, x, y, z); // 元の関数と比較 System.out.println(String.format("%5.2f\t%8.5f\t%8.5f\t%8.5f", d1, d2, d3, d2 - d3)); } } // 元の関数 private static double f(double x) { return x - Math.pow(x,3) / (3 * 2) + Math.pow(x,5) / (5 * 4 * 3 * 2); } // Spline (スプライン) 補間 private static double spline(double d, double[] x, double[] y, double[] z) { // 補間関数値がどの区間にあるか int k = -1; for (int i = 1; i < N; i++) { if (d <= x[i]) { k = i - 1; break; } } if (k < 0) k = N - 1; double d1 = x[k+1] - d; double d2 = d - x[k]; double d3 = x[k+1] - x[k]; return (z[k] * Math.pow(d1,3) + z[k+1] * Math.pow(d2,3)) / (6.0 * d3) + (y[k] / d3 - z[k] * d3 / 6.0) * d1 + (y[k+1] / d3 - z[k+1] * d3 / 6.0) * d2; } }
Z:\>javac Java0705.java Z:\>java Java0705 -4.50 -4.68984 -4.68984 0.00000 -4.00 -1.86667 -2.90573 1.03906 -3.50 -0.73099 -1.41849 0.68750 -3.00 -0.52500 -0.52500 0.00000 -2.50 -0.70964 -0.39714 -0.31250 -2.00 -0.93333 -0.70677 -0.22656 -1.50 -1.00078 -1.00078 -0.00000 -1.00 -0.84167 -0.92760 0.08594 -0.50 -0.47943 -0.54193 0.06250 0.00 0.00000 0.00000 0.00000 0.50 0.47943 0.54193 -0.06250 1.00 0.84167 0.92760 -0.08594 1.50 1.00078 1.00078 0.00000 2.00 0.93333 0.70677 0.22656 2.50 0.70964 0.39714 0.31250 3.00 0.52500 0.52500 -0.00000 3.50 0.73099 1.41849 -0.68750 4.00 1.86667 2.90573 -1.03906 4.50 4.68984 4.68984 0.00000
C++
#include <iostream> #include <iomanip> #include <math.h> using namespace std; // データ点の数 const int N = 7; // 元の関数 double f(double x); // Spline (スプライン) 補間 double spline(double d, double x[], double y[], double z[]); int main() { double x[N], y[N]; // 1.5刻みで -4.5~4.5 まで, 7点だけ値をセット for (int i = 0; i < N; i++) { double d = i * 1.5 - 4.5; x[i] = d; y[i] = f(d); } // 3項方程式の係数の表を作る double a[N], b[N], c[N], d[N]; for (int i = 1; i < N - 1; i++) { a[i] = x[i] - x[i-1]; b[i] = 2.0 * (x[i+1] - x[i-1]); c[i] = x[i+1] - x[i]; d[i] = 6.0 * ((y[i+1] - y[i]) / (x[i+1] - x[i]) - (y[i] - y[i-1]) / (x[i] - x[i-1])); } // 3項方程式を解く (ト-マス法) double g[N], s[N]; g[1] = b[1]; s[1] = d[1]; for (int i = 2; i < N - 1; i++) { g[i] = b[i] - a[i] * c[i-1] / g[i-1]; s[i] = d[i] - a[i] * s[i-1] / g[i-1]; } double z[N]; z[0] = 0; z[N-1] = 0; z[N-2] = s[N-2] / g[N-2]; for (int i = N - 3; i >= 1; i--) { z[i] = (s[i] - c[i] * z[i+1]) / g[i]; } // 0.5刻みで 与えられていない値を補間 for (int i = 0; i <= 18; i++) { double d = i * 0.5 - 4.5; double d1 = f(d); double d2 = spline(d, x, y, z); // 元の関数と比較 cout << setw(5) << fixed << setprecision(2) << d << '\t'; cout << setw(8) << fixed << setprecision(5) << d1 << '\t'; cout << setw(8) << fixed << setprecision(5) << d2 << '\t'; cout << setw(8) << fixed << setprecision(5) << d1 - d2 << endl; } return 0; } // 元の関数 double f(double x) { return x - pow(x,3) / (3 * 2) + pow(x,5) / (5 * 4 * 3 * 2); } // Spline (スプライン) 補間 double spline(double d, double x[], double y[], double z[]) { // 補間関数値がどの区間にあるか int k = -1; for (int i = 1; i < N; i++) { if (d <= x[i]) { k = i - 1; break; } } if (k < 0) k = N - 1; double d1 = x[k+1] - d; double d2 = d - x[k]; double d3 = x[k+1] - x[k]; return (z[k] * pow(d1,3) + z[k+1] * pow(d2,3)) / (6.0 * d3) + (y[k] / d3 - z[k] * d3 / 6.0) * d1 + (y[k+1] / d3 - z[k+1] * d3 / 6.0) * d2; }
Z:\>bcc32 -q CP0705.cpp cp0705.cpp: Z:\>CP0705 -4.50 -4.68984 -4.68984 0.00000 -4.00 -1.86667 -2.90573 1.03906 -3.50 -0.73099 -1.41849 0.68750 -3.00 -0.52500 -0.52500 0.00000 -2.50 -0.70964 -0.39714 -0.31250 -2.00 -0.93333 -0.70677 -0.22656 -1.50 -1.00078 -1.00078 0.00000 -1.00 -0.84167 -0.92760 0.08594 -0.50 -0.47943 -0.54193 0.06250 0.00 0.00000 0.00000 0.00000 0.50 0.47943 0.54193 -0.06250 1.00 0.84167 0.92760 -0.08594 1.50 1.00078 1.00078 0.00000 2.00 0.93333 0.70677 0.22656 2.50 0.70964 0.39714 0.31250 3.00 0.52500 0.52500 0.00000 3.50 0.73099 1.41849 -0.68750 4.00 1.86667 2.90573 -1.03906 4.50 4.68984 4.68984 0.00000
Objective-C
#import <Foundation/Foundation.h> #import <math.h> // データ点の数 const int N = 7; // 元の関数 double f(double x); // Spline (スプライン) 補間 double spline(double d, double x[], double y[], double z[]); int main() { int i; double x[N], y[N]; // 1.5刻みで -4.5~4.5 まで, 7点だけ値をセット for (i = 0; i < N; i++) { double d = i * 1.5 - 4.5; x[i] = d; y[i] = f(d); } // 3項方程式の係数の表を作る double a[N], b[N], c[N], d[N]; for (i = 1; i < N - 1; i++) { a[i] = x[i] - x[i-1]; b[i] = 2.0 * (x[i+1] - x[i-1]); c[i] = x[i+1] - x[i]; d[i] = 6.0 * ((y[i+1] - y[i]) / (x[i+1] - x[i]) - (y[i] - y[i-1]) / (x[i] - x[i-1])); } // 3項方程式を解く (ト-マス法) double g[N], s[N]; g[1] = b[1]; s[1] = d[1]; for (i = 2; i < N - 1; i++) { g[i] = b[i] - a[i] * c[i-1] / g[i-1]; s[i] = d[i] - a[i] * s[i-1] / g[i-1]; } double z[N]; z[0] = 0; z[N-1] = 0; z[N-2] = s[N-2] / g[N-2]; for (i = N - 3; i >= 1; i--) { z[i] = (s[i] - c[i] * z[i+1]) / g[i]; } // 0.5刻みで 与えられていない値を補間 for (i = 0; i <= 18; i++) { double d = i * 0.5 - 4.5; double d1 = f(d); double d2 = spline(d, x, y, z); // 元の関数と比較 printf("%5.2f\t%8.5f\t%8.5f\t%8.5f\n", d, d1, d2, d1 - d2); } return 0; } // 元の関数 double f(double x) { return x - pow(x,3) / (3 * 2) + pow(x,5) / (5 * 4 * 3 * 2); } // Spline (スプライン) 補間 double spline(double d, double x[], double y[], double z[]) { // 補間関数値がどの区間にあるか int i, k = -1; for (i = 1; i < N; i++) { if (d <= x[i]) { k = i - 1; break; } } if (k < 0) k = N - 1; double d1 = x[k+1] - d; double d2 = d - x[k]; double d3 = x[k+1] - x[k]; return (z[k] * pow(d1,3) + z[k+1] * pow(d2,3)) / (6.0 * d3) + (y[k] / d3 - z[k] * d3 / 6.0) * d1 + (y[k+1] / d3 - z[k+1] * d3 / 6.0) * d2; }
xxxxxx@yyyyyy /Z $ gcc -o OC0705 OC0705.m -lobjc -lgnustep-base -I $INCLUDE -L $LIB $CFLAGS xxxxxx@yyyyyy /Z $ OC0705 -4.50 -4.68984 -4.68984 0.00000 -4.00 -1.86667 -2.90573 1.03906 -3.50 -0.73099 -1.41849 0.68750 -3.00 -0.52500 -0.52500 0.00000 -2.50 -0.70964 -0.39714 -0.31250 -2.00 -0.93333 -0.70677 -0.22656 -1.50 -1.00078 -1.00078 0.00000 -1.00 -0.84167 -0.92760 0.08594 -0.50 -0.47943 -0.54193 0.06250 0.00 0.00000 0.00000 0.00000 0.50 0.47943 0.54193 -0.06250 1.00 0.84167 0.92760 -0.08594 1.50 1.00078 1.00078 0.00000 2.00 0.93333 0.70677 0.22656 2.50 0.70964 0.39714 0.31250 3.00 0.52500 0.52500 0.00000 3.50 0.73099 1.41849 -0.68750 4.00 1.86667 2.90573 -1.03906 4.50 4.68984 4.68984 0.00000
D
import std.stdio; import std.math; // データ点の数 const int N = 7; void main(string[] args) { double x[N]; double y[N]; // 1.5刻みで -4.5~4.5 まで, 7点だけ値をセット for (int i = 0; i < N; i++) { double d = i * 1.5 - 4.5; x[i] = d; y[i] = f(d); } // 3項方程式の係数の表を作る double a[N]; double b[N]; double c[N]; double d[N]; for (int i = 1; i < N - 1; i++) { a[i] = x[i] - x[i-1]; b[i] = 2.0 * (x[i+1] - x[i-1]); c[i] = x[i+1] - x[i]; d[i] = 6.0 * ((y[i+1] - y[i]) / (x[i+1] - x[i]) - (y[i] - y[i-1]) / (x[i] - x[i-1])); } // 3項方程式を解く (ト-マス法) double g[N]; double s[N]; g[1] = b[1]; s[1] = d[1]; for (int i = 2; i < N - 1; i++) { g[i] = b[i] - a[i] * c[i-1] / g[i-1]; s[i] = d[i] - a[i] * s[i-1] / g[i-1]; } double z[N]; z[0] = 0; z[N-1] = 0; z[N-2] = s[N-2] / g[N-2]; for (int i = N - 3; i >= 1; i--) { z[i] = (s[i] - c[i] * z[i+1]) / g[i]; } // 0.5刻みで 与えられていない値を補間 for (int i = 0; i <= 18; i++) { double d1 = i * 0.5 - 4.5; double d2 = f(d1); double d3 = spline(d1, x, y, z); // 元の関数と比較 writefln("%5.2f\t%8.5f\t%8.5f\t%8.5f", d1, d2, d3, d2 - d3); } } // 元の関数 double f(double x) { return x - pow(x,3) / (3 * 2) + pow(x,5) / (5 * 4 * 3 * 2); } // Spline (スプライン) 補間 double spline(double d, double x[], double y[], double z[]) { // 補間関数値がどの区間にあるか int k = -1; for (int i = 1; i < N; i++) { if (d <= x[i]) { k = i - 1; break; } } if (k < 0) k = N - 1; double d1 = x[k+1] - d; double d2 = d - x[k]; double d3 = x[k+1] - x[k]; return (z[k] * pow(d1,3) + z[k+1] * pow(d2,3)) / (6.0 * d3) + (y[k] / d3 - z[k] * d3 / 6.0) * d1 + (y[k+1] / d3 - z[k+1] * d3 / 6.0) * d2; }
Z:\>dmd D0705.d Z:\>D0705 -4.50 -4.68984 -4.68984 0.00000 -4.00 -1.86667 -2.90573 1.03906 -3.50 -0.73099 -1.41849 0.68750 -3.00 -0.52500 -0.52500 0.00000 -2.50 -0.70964 -0.39714 -0.31250 -2.00 -0.93333 -0.70677 -0.22656 -1.50 -1.00078 -1.00078 0.00000 -1.00 -0.84167 -0.92760 0.08593 -0.50 -0.47943 -0.54193 0.06250 0.00 0.00000 -0.00000 0.00000 0.50 0.47943 0.54193 -0.06250 1.00 0.84167 0.92760 -0.08593 1.50 1.00078 1.00078 0.00000 2.00 0.93333 0.70677 0.22656 2.50 0.70964 0.39714 0.31250 3.00 0.52500 0.52500 0.00000 3.50 0.73099 1.41849 -0.68750 4.00 1.86667 2.90573 -1.03906 4.50 4.68984 4.68984 0.00000
Go
package main import "fmt" import "math" // データ点の数 const N = 7 func main() { var x [N]float64 var y [N]float64 // 1.5刻みで -4.5~4.5 まで, 7点だけ値をセット for i := 0; i < N; i++ { var d float64 = float64(i) * 1.5 - 4.5 x[i] = d y[i] = f(d) } // 3項方程式の係数の表を作る var a [N]float64 var b [N]float64 var c [N]float64 var d [N]float64 for i := 1; i < N - 1; i++ { a[i] = x[i] - x[i-1] b[i] = 2.0 * (x[i+1] - x[i-1]) c[i] = x[i+1] - x[i] d[i] = 6.0 * ((y[i+1] - y[i]) / (x[i+1] - x[i]) - (y[i] - y[i-1]) / (x[i] - x[i-1])) } // 3項方程式を解く (ト-マス法) var g [N]float64 var s [N]float64 g[1] = b[1] s[1] = d[1] for i := 2; i < N - 1; i++ { g[i] = b[i] - a[i] * c[i-1] / g[i-1] s[i] = d[i] - a[i] * s[i-1] / g[i-1] } var z [N]float64 z[0] = 0 z[N-1] = 0 z[N-2] = s[N-2] / g[N-2] for i := N - 3; i >= 1; i-- { z[i] = (s[i] - c[i] * z[i+1]) / g[i] } // 0.5刻みで 与えられていない値を補間 for i := 0; i <= 18; i++ { var d1 float64 = float64(i) * 0.5 - 4.5 var d2 float64 = f(d1) var d3 float64 = spline(d1, x[:], y[:], z[:]) // 元の関数と比較 fmt.Printf("%5.2f\t%8.5f\t%8.5f\t%8.5f\n", d1, d2, d3, d2 - d3) } } // 元の関数 func f(x float64) float64 { return x - math.Pow(x,3) / (3 * 2) + math.Pow(x,5) / (5 * 4 * 3 * 2) } // Spline (スプライン) 補間 func spline(d float64, x []float64, y []float64, z []float64) float64 { // 補間関数値がどの区間にあるか k := -1 for i := 1; i < N; i++ { if d <= x[i] { k = i - 1 break } } if k < 0 { k = N - 1 } var d1 float64 = x[k+1] - d var d2 float64 = d - x[k] var d3 float64 = x[k+1] - x[k] return (z[k] * math.Pow(d1,3) + z[k+1] * math.Pow(d2,3)) / (6.0 * d3) + (y[k] / d3 - z[k] * d3 / 6.0) * d1 + (y[k+1] / d3 - z[k+1] * d3 / 6.0) * d2 }
Z:\>8g GO0705.go Z:\>8l -o GO0705.exe GO0705.8 Z:\>GO0705 -4.50 -4.68984 -4.68984 0.00000 -4.00 -1.86667 -2.90573 1.03906 -3.50 -0.73099 -1.41849 0.68750 -3.00 -0.52500 -0.52500 0.00000 -2.50 -0.70964 -0.39714 -0.31250 -2.00 -0.93333 -0.70677 -0.22656 -1.50 -1.00078 -1.00078 -0.00000 -1.00 -0.84167 -0.92760 0.08594 -0.50 -0.47943 -0.54193 0.06250 0.00 0.00000 0.00000 0.00000 0.50 0.47943 0.54193 -0.06250 1.00 0.84167 0.92760 -0.08594 1.50 1.00078 1.00078 0.00000 2.00 0.93333 0.70677 0.22656 2.50 0.70964 0.39714 0.31250 3.00 0.52500 0.52500 -0.00000 3.50 0.73099 1.41849 -0.68750 4.00 1.86667 2.90573 -1.03906 4.50 4.68984 4.68984 0.00000
Scala
object Scala0705 { // データ点の数 - 1 val N = 6 def main(args: Array[String]) { // 1.5刻みで -4.5~4.5 まで, 7点だけ値をセット val x = (0 to N).map(_ * 1.5 - 4.5) val y = x.map(f) // 3項方程式の係数の表を作る val a = Array.ofDim[Double](N) val b = Array.ofDim[Double](N) val c = Array.ofDim[Double](N) val d = Array.ofDim[Double](N) for (i <- 1 to N - 1) { a(i) = x(i) - x(i-1) b(i) = 2.0 * (x(i+1) - x(i-1)) c(i) = x(i+1) - x(i) d(i) = 6.0 * ((y(i+1) - y(i)) / (x(i+1) - x(i)) - (y(i) - y(i-1)) / (x(i) - x(i-1))) } // 3項方程式を解く (ト-マス法) val g = Array.ofDim[Double](N) val s = Array.ofDim[Double](N) g(1) = b(1) s(1) = d(1) for (i <- 2 to N - 1) { g(i) = b(i) - a(i) * c(i-1) / g(i-1) s(i) = d(i) - a(i) * s(i-1) / g(i-1) } val z = Array.ofDim[Double](N + 1) z(0) = 0 z(N) = 0 z(N-1) = s(N-1) / g(N-1) for (i <- N - 2 to 1 by -1) z(i) = (s(i) - c(i) * z(i+1)) / g(i) // 0.5刻みで 与えられていない値を補間 val d1 = (0 to 18).map(_ * 0.5 - 4.5) val d2 = d1.map(f) val d3 = d1.map(spline(_, x, y, z)) (d1 zip d2 zip d3).foreach { case ((d1, d2), d3) => println("%5.2f\t%8.5f\t%8.5f\t%8.5f".format(d1, d2, d3, d2 - d3)) } } // 元の関数 def f(x:Double) = { x - Math.pow(x,3) / (3 * 2) + Math.pow(x,5) / (5 * 4 * 3 * 2) } // Spline (スプライン) 補間 def spline(d:Double, x:IndexedSeq[Double], y:IndexedSeq[Double], z:IndexedSeq[Double]) = { // 補間関数値がどの区間にあるか var k = -1 for (i <- N to 1 by -1) { if (d <= x(i)) k = i - 1 } if (k < 0) k = N val d1 = x(k+1) - d val d2 = d - x(k) val d3 = x(k+1) - x(k) (z(k) * Math.pow(d1,3) + z(k+1) * Math.pow(d2,3)) / (6.0 * d3) + (y(k) / d3 - z(k) * d3 / 6.0) * d1 + (y(k+1) / d3 - z(k+1) * d3 / 6.0) * d2 } }
Z:\>scala Scala0705.scala -4.50 -4.68984 -4.68984 0.00000 -4.00 -1.86667 -2.90573 1.03906 -3.50 -0.73099 -1.41849 0.68750 -3.00 -0.52500 -0.52500 0.00000 -2.50 -0.70964 -0.39714 -0.31250 -2.00 -0.93333 -0.70677 -0.22656 -1.50 -1.00078 -1.00078 -0.00000 -1.00 -0.84167 -0.92760 0.08594 -0.50 -0.47943 -0.54193 0.06250 0.00 0.00000 0.00000 0.00000 0.50 0.47943 0.54193 -0.06250 1.00 0.84167 0.92760 -0.08594 1.50 1.00078 1.00078 0.00000 2.00 0.93333 0.70677 0.22656 2.50 0.70964 0.39714 0.31250 3.00 0.52500 0.52500 -0.00000 3.50 0.73099 1.41849 -0.68750 4.00 1.86667 2.90573 -1.03906 4.50 4.68984 4.68984 0.00000
F#
module Fs0705 open System // データ点の数 - 1 let N = 6 // 元の関数 let f (x:double):double = x - Math.Pow(x,3.0) / (float (3 * 2)) + Math.Pow(x,5.0) / (float (5 * 4 * 3 * 2)) // Spline (スプライン) 補間 let spline(d:double) (x:double list) (y:double list) (z:double list) = // 補間関数値がどの区間にあるか let mutable k = -1 for i in [N..(-1)..1] do if d <= x.[i] then k <- i - 1 if k < 0 then k <- N let d1 = x.[k+1] - d let d2 = d - x.[k] let d3 = x.[k+1] - x.[k] (z.[k] * Math.Pow(d1,3.0) + z.[k+1] * Math.Pow(d2,3.0)) / (6.0 * d3) + (y.[k] / d3 - z.[k] * d3 / 6.0) * d1 + (y.[k+1] / d3 - z.[k+1] * d3 / 6.0) * d2 // 1.5刻みで -4.5~4.5 まで, 7点だけ値をセット let x = [0..N] |> List.map(fun i -> (float i) * 1.5 - 4.5) let y = x |> List.map(f) // 3項方程式の係数の表を作る let a = Array.zeroCreate<double> N let b = Array.zeroCreate<double> N let c = Array.zeroCreate<double> N let d = Array.zeroCreate<double> N for i in [1..N - 1] do a.[i] <- x.[i] - x.[i-1] b.[i] <- 2.0 * (x.[i+1] - x.[i-1]) c.[i] <- x.[i+1] - x.[i] d.[i] <- 6.0 * ((y.[i+1] - y.[i]) / (x.[i+1] - x.[i]) - (y.[i] - y.[i-1]) / (x.[i] - x.[i-1])) // 3項方程式を解く (ト-マス法) let g = Array.zeroCreate<double> N let s = Array.zeroCreate<double> N g.[1] <- b.[1] s.[1] <- d.[1] for i in [2..N - 1] do g.[i] <- b.[i] - a.[i] * c.[i-1] / g.[i-1] s.[i] <- d.[i] - a.[i] * s.[i-1] / g.[i-1] let z = Array.zeroCreate<double> (N+1) z.[0] <- 0.0 z.[N] <- 0.0 z.[N-1] <- s.[N-1] / g.[N-1] for i in [(N-2)..(-1)..1] do z.[i] <- (s.[i] - c.[i] * z.[i+1]) / g.[i] // 0.5刻みで 与えられていない値を補間 let d1 = [0..18] |> List.map(fun i -> (float i) * 0.5 - 4.5) let d2 = d1 |> List.map(f) let d3 = d1 |> List.map(fun d -> (spline d x y (Array.toList(z)))) (List.zip (List.zip d1 d2) d3) |> List.iter (fun ((d1, d2), d3) -> printfn "%5.2f\t%8.5f\t%8.5f\t%8.5f" d1 d2 d3 (d2 - d3)) exit 0
Z:\>fsi --nologo --quiet Fs0705.fs -4.50 -4.68984 -4.68984 0.00000 -4.00 -1.86667 -2.90573 1.03906 -3.50 -0.73099 -1.41849 0.68750 -3.00 -0.52500 -0.52500 0.00000 -2.50 -0.70964 -0.39714 -0.31250 -2.00 -0.93333 -0.70677 -0.22656 -1.50 -1.00078 -1.00078 0.00000 -1.00 -0.84167 -0.92760 0.08594 -0.50 -0.47943 -0.54193 0.06250 0.00 0.00000 0.00000 0.00000 0.50 0.47943 0.54193 -0.06250 1.00 0.84167 0.92760 -0.08594 1.50 1.00078 1.00078 0.00000 2.00 0.93333 0.70677 0.22656 2.50 0.70964 0.39714 0.31250 3.00 0.52500 0.52500 0.00000 3.50 0.73099 1.41849 -0.68750 4.00 1.86667 2.90573 -1.03906 4.50 4.68984 4.68984 0.00000
Clojure
(def N 7) ; 元の関数 (defn f[x] (+ (- x (/ (Math/pow x 3.0) (* 3 2))) (/ (Math/pow x 5.0) (* 5 (* 4 (* 3 2)))))) ; Spline (スプライン) 補間 (defn spline [d x y z] ; 補間関数値がどの区間にあるか (def k -1) (doseq [i (range 1 N)] (if (and (<= d (nth x i)) (< k 0)) (def k (- i 1)) ) ) (if (< k 0) (def k N)) (def d1 (- (nth x (+ k 1)) d)) (def d2 (- d (nth x k))) (def d3 (- (nth x (+ k 1)) (nth x k))) (def a1 (* (nth z k) (Math/pow d1 3.0))) (def a2 (* (nth z (+ k 1)) (Math/pow d2 3.0))) (def a3 (/ (+ a1 a2) (* 6.0 d3))) (def b1 (/ (nth y k) d3)) (def b2 (* (nth z k) d3)) (def b3 (/ b2 6.0)) (def b4 (* (- b1 b3) d1)) (def c1 (/ (nth y (+ k 1)) d3)) (def c2 (* (nth z (+ k 1)) d3)) (def c3 (/ c2 6.0)) (def c4 (* (- c1 c3) d2)) (+ (+ a3 b4) c4) ) ; 1.5刻みで -4.5~4.5 まで, 7点だけ値をセット (def x (map #(- (* % 1.5) 4.5) (range 0 N))) (def y (map #(f %) x)) ; 3項方程式の係数の表を作る (def a (list 0.0)) (def b (list 0.0)) (def c (list 0.0)) (def d (list 0.0)) (doseq [i (range 1 (- N 1))] (def a (cons (- (nth x i ) (nth x (- i 1))) a)) (def b (cons (* 2.0 (- (nth x (+ i 1)) (nth x (- i 1)))) b)) (def c (cons (- (nth x (+ i 1)) (nth x i )) c)) (def d (cons (* 6.0 (- (/ (- (nth y(+ i 1)) (nth y i)) (- (nth x(+ i 1)) (nth x i))) (/ (- (nth y i) (nth y (- i 1))) (- (nth x i) (nth x (- i 1)))))) d))) (def a (reverse a)) (def b (reverse b)) (def c (reverse c)) (def d (reverse d)) ; 3項方程式を解く (ト-マス法) (def g (list (nth b 1) 0.0)) (def s (list (nth d 1) 0.0)) (doseq [i (range 2 (- N 1))] (def w (nth g 0)) (def g (cons (- (nth b i) (/ (* (nth a i) (nth c (- i 1))) w)) g)) (def s (cons (- (nth d i) (/ (* (nth a i) (nth s 0)) w)) s)) ) (def g (reverse g)) (def s (reverse s)) (def z (list 0.0)) (def z (cons (/ (nth s (- N 2)) (nth g (- N 2))) z)) (doseq [i (reverse (range 1 (- N 2)))] (def z (cons (/ (- (nth s i) (* (nth c i) (nth z 0))) (nth g i)) z)) ) (def z (cons 0.0 z)) ; 0.5刻みで 与えられていない値を補間 (def d1 (map #(- (* % 0.5) 4.5) (range 0 19))) (def d2 (map #(f %) d1)) (def d3 (map #(spline % x y z) d1)) (doseq [d (map list d1 d2 d3)] (def d1 (nth d 0)) (def d2 (nth d 1)) (def d3 (nth d 2)) (println (format "%5.2f\t%8.5f\t%8.5f\t%8.5f" d1 d2 d3 (- d2 d3))))
Z:\>java -cp C:\ProgramFiles\clojure-1.5.1\clojure-1.5.1.jar clojure.main Clj0705.clj -4.50 -4.68984 -4.68984 0.00000 -4.00 -1.86667 -2.90573 1.03906 -3.50 -0.73099 -1.41849 0.68750 -3.00 -0.52500 -0.52500 0.00000 -2.50 -0.70964 -0.39714 -0.31250 -2.00 -0.93333 -0.70677 -0.22656 -1.50 -1.00078 -1.00078 -0.00000 -1.00 -0.84167 -0.92760 0.08594 -0.50 -0.47943 -0.54193 0.06250 0.00 0.00000 0.00000 0.00000 0.50 0.47943 0.54193 -0.06250 1.00 0.84167 0.92760 -0.08594 1.50 1.00078 1.00078 0.00000 2.00 0.93333 0.70677 0.22656 2.50 0.70964 0.39714 0.31250 3.00 0.52500 0.52500 -0.00000 3.50 0.73099 1.41849 -0.68750 4.00 1.86667 2.90573 -1.03906 4.50 4.68984 4.68984 0.00000
Haskell
import Text.Printf import Control.Monad -- データ点の数 - 1 n = 6 :: Int -- 元の関数 f::Double->Double f x = x - (x ^ 3) / (fromIntegral (3 * 2)) + (x ^ 5) / (fromIntegral (5 * 4 * 3 * 2)) -- 3項方程式を解く (ト-マス法) thomas::Int->[Double]->[Double]->[Double]->[Double]->[Double]->[Double]->([Double], [Double]) thomas i a b c d gs ss = let g = b!!i - a!!i * c!!(i-1) / gs!!0 s = d!!i - a!!i * ss!!0 / gs!!0 in if i == (n - 1) then (reverse (g:gs), reverse (s:ss)) else (thomas (i + 1) a b c d (g:gs) (s:ss)) thomas2::Int->[Double]->[Double]->[Double]->[Double]->[Double] thomas2 i g s c zs = let z = (s!!i - c!!i * zs!!0) / g!!i in if i == 1 then 0.0 : z : zs else thomas2 (i - 1) g s c (z:zs) -- Spline (スプライン) 補間 spline::Double->[Double]->[Double]->[Double]->Double spline d x y z = let -- 補間関数値がどの区間にあるか k = if d <= x!!0 then 0 else (length $ filter (\i -> i < d) $ x) - 1 d1 = x!!(k+1) - d d2 = d - x!!k d3 = x!!(k+1) - x!!k in (z!!k * (d1 ^ 3) + z!!(k+1) * (d2 ^ 3)) / (6.0 * d3) + (y!!k / d3 - z!!k * d3 / 6.0) * d1 + (y!!(k+1) / d3 - z!!(k+1) * d3 / 6.0) * d2 main = do -- 1.5刻みで -4.5~4.5 まで, 7点だけ値をセット let x = map(\i -> (fromIntegral i) * 1.5 - 4.5) [0..n] let y = map(\i -> f(i)) x -- 3項方程式の係数の表を作る let a = 0.0 : map(\i -> x!!i - x!!(i-1)) [1..n - 1] let b = 0.0 : map(\i -> 2 * (x!!(i+1) - x!!(i-1))) [1..n - 1] let c = 0.0 : map(\i -> x!!(i+1) - x!!i) [1..n - 1] let d = 0.0 : map(\i -> 6 * ((y!!(i+1) - y!!i) / (x!!(i+1) - x!!i) - (y!!i - y!!(i-1)) / (x!!i - x!!(i-1)))) [1..n - 1] -- 3項方程式を解く (ト-マス法) let (g, s) = (thomas 2 a b c d [b!!1, 0.0] [d!!1, 0.0]) let z = (thomas2 (n - 2) g s c [s!!(n-1) / g!!(n-1), 0.0]) -- 0.5刻みで 与えられていない値を補間 let d1 = map(\i -> (fromIntegral i) * 0.5 - 4.5) [0..18] let d2 = map(\i -> (f i)) d1 let d3 = map(\i -> (spline i x y z)) d1 forM_ (zip (zip d1 d2) d3) $ \((d1, d2), d3) -> do printf "%5.2f\t%8.5f\t%8.5f\t%8.5f\n" d1 d2 d3 (d2 - d3)
Z:\>runghc Hs0705.hs -4.50 -4.68984 -4.68984 0.00000 -4.00 -1.86667 -2.90573 1.03906 -3.50 -0.73099 -1.41849 0.68750 -3.00 -0.52500 -0.52500 0.00000 -2.50 -0.70964 -0.39714 -0.31250 -2.00 -0.93333 -0.70677 -0.22656 -1.50 -1.00078 -1.00078 -0.00000 -1.00 -0.84167 -0.92760 0.08594 -0.50 -0.47943 -0.54193 0.06250 0.00 0.00000 0.00000 0.00000 0.50 0.47943 0.54193 -0.06250 1.00 0.84167 0.92760 -0.08594 1.50 1.00078 1.00078 0.00000 2.00 0.93333 0.70677 0.22656 2.50 0.70964 0.39714 0.31250 3.00 0.52500 0.52500 -0.00000 3.50 0.73099 1.41849 -0.68750 4.00 1.86667 2.90573 -1.03906 4.50 4.68984 4.68984 0.00000