さまざまな言語で数値計算
Only Do What Only You Can Do
はさみうち法
非線形方程式の解法(はさみうち法)を利用して2の平方根を求める .
考え方は、2分法とほとんど同じ.
1. まず, 条件 $ a < b, f(a) < 0, f(b) > 0 $ を満たす点 $ a, b $ を考えると,
関数 $ f(x) $ の解は, 区間 $ (a,b) $ の中に存在する.
2. 次に, 点 $ (a,f(a)) $ と 点 $ (b,f(b)) $ を結ぶ直線と $x$ 軸の交点
を考えると,
$ f(c) < 0 $ であれば, 解は, 区間 $ (c,b) $ の中に存在し,
同様に, $ f(c) > 0 $ であれば, 区間 $ (a,c) $ の中に存在する.
3. この作業を繰り返して, 区間を絞り込んで行くことで解を求める.
※ ちなみに, 区間 $ (a,b) $ とは, 両端を含まない数の集合で, 開区間という.
$ (a,b) = \{x | a < x < b \} $
また, 両端を含む数の集合は, 閉区間という.
$ [a,b] = \{x | a \leq x \leq b \} $
VBScript
Option Explicit Dim a: a = 1.0 Dim b: b = 2.0 WScript.StdOut.Write Right(Space(12) & FormatNumber(falseposition(a, b), 10, -1, 0, 0), 12) & vbNewLine Private Function falseposition(ByVal a, ByVal b) Dim c Do While(True) '点 (a,f(a)) と 点 (b,f(b)) を結ぶ直線と x軸の交点 c = (a * f(b) - b * f(a)) / (f(b) - f(a)) WScript.StdOut.Write Right(Space(12) & FormatNumber(c, 10, -1, 0, 0), 12) & vbTab WScript.StdOut.Write Right(Space(12) & FormatNumber(c - Sqr(2), 10, -1, 0, 0), 12) & vbNewLine Dim fc: fc = f(c) If Abs(fc) < 0.0000000001 Then Exit Do If fc < 0 Then 'f(c) < 0 であれば, 解は区間 (c, b) の中に存在 a = c Else 'f(c) > 0 であれば, 解は区間 (a, c) の中に存在 b = c End If Loop falseposition = c End Function Private Function f(ByVal x) f = x * x - 2.0 End Function
Z:\>cscript //nologo Z:\0902.vbs 1.3333333333 0.0808802290 1.4000000000 0.0142135624 1.4117647059 0.0024488565 1.4137931034 0.0004204589 1.4141414141 0.0000721482 1.4142011834 0.0000123789 1.4142114385 0.0000021239 1.4142131980 0.0000003644 1.4142134999 0.0000000625 1.4142135516 0.0000000107 1.4142135605 0.0000000018 1.4142135621 0.0000000003 1.4142135623 0.0000000001 1.4142135624 0.0000000000 1.4142135624
JScript
var a = 1 var b = 2 WScript.StdOut.Write((" " + falseposition(a, b).toFixed(10) ).slice(-12) + "\n") function falseposition(a, b) { var c while (true) { // 点 (a,f(a)) と 点 (b,f(b)) を結ぶ直線と x軸の交点 c = (a * f(b) - b * f(a)) / (f(b) - f(a)) WScript.StdOut.Write((" " + c.toFixed(10) ).slice(-12) + "\t") WScript.StdOut.Write((" " + (c - Math.sqrt(2)).toFixed(10) ).slice(-12) + "\n") var fc = f(c) if (Math.abs(fc) < 0.0000000001) break if (fc < 0){ // f(c) < 0 であれば, 解は区間 (c, b) の中に存在 a = c } else { // f(c) > 0 であれば, 解は区間 (a, c) の中に存在 b = c } } return c } function f(x) { return x * x - 2 }
Z:\>cscript //nologo Z:\0902.js 1.3333333333 0.0808802290 1.4000000000 0.0142135624 1.4117647059 0.0024488565 1.4137931034 0.0004204589 1.4141414141 0.0000721482 1.4142011834 0.0000123789 1.4142114385 0.0000021239 1.4142131980 0.0000003644 1.4142134999 0.0000000625 1.4142135516 0.0000000107 1.4142135605 0.0000000018 1.4142135621 0.0000000003 1.4142135623 0.0000000000 1.4142135624 0.0000000000 1.4142135624
PowerShell
function falseposition($a, $b) { while ($true) { # 点 (a,f(a)) と 点 (b,f(b)) を結ぶ直線と x軸の交点 $c = ($a * (f $b) - $b * (f $a)) / ((f $b) - (f $a)) Write-Host ([String]::Format("{0,12:F10}`t{1,13:F10}", $c, $c - [Math]::Sqrt(2))) $fc = f($c) if ([Math]::Abs($fc) -lt 0.0000000001) { break } if ($fc -lt 0) { # f(c) < 0 であれば, 解は区間 (c, b) の中に存在 $a = $c } else { # f(c) > 0 であれば, 解は区間 (a, c) の中に存在 $b = $c } } return $c } function f($x) { return $x * $x - 2 } $a = 1 $b = 2 Write-Host ([String]::Format("{0,12:F10}", (falseposition $a $b)))
Z:\>powershell -file Z:\0902.ps1 1.3333333333 -0.0808802290 1.4000000000 -0.0142135624 1.4117647059 -0.0024488565 1.4137931034 -0.0004204589 1.4141414141 -0.0000721482 1.4142011834 -0.0000123789 1.4142114385 -0.0000021239 1.4142131980 -0.0000003644 1.4142134999 -0.0000000625 1.4142135516 -0.0000000107 1.4142135605 -0.0000000018 1.4142135621 -0.0000000003 1.4142135623 -0.0000000001 1.4142135624 0.0000000000 1.4142135624
Perl
my $a = 1; my $b = 2; printf("%12.10f\n", falseposition($a, $b)); sub falseposition { my ($a, $b) = @_; my $c; while (1) { # 点 (a,f(a)) と 点 (b,f(b)) を結ぶ直線と x軸の交点 $c = ($a * f($b) - $b * f($a)) / (f($b) - f($a)); printf("%12.10f\t%13.10f\n", $c, $c - sqrt(2)); my $fc = f($c); if (abs($fc) < 0.0000000001) { last; } if ($fc < 0) { # f(c) < 0 であれば, 解は区間 (c, b) の中に存在 $a = $c; } else { # f(c) > 0 であれば, 解は区間 (a, c) の中に存在 $b = $c; } } $c; } sub f { my ($x) = @_; $x * $x - 2; }
Z:\>perl Z:\0902.pl 1.3333333333 -0.0808802290 1.4000000000 -0.0142135624 1.4117647059 -0.0024488565 1.4137931034 -0.0004204589 1.4141414141 -0.0000721482 1.4142011834 -0.0000123789 1.4142114385 -0.0000021239 1.4142131980 -0.0000003644 1.4142134999 -0.0000000625 1.4142135516 -0.0000000107 1.4142135605 -0.0000000018 1.4142135621 -0.0000000003 1.4142135623 -0.0000000001 1.4142135624 -0.0000000000 1.4142135624
PHP
<?php $a = 1; $b = 2; printf("%12.10f\n", falseposition($a, $b)); function falseposition($a, $b) { while (TRUE) { # 点 (a,f(a)) と 点 (b,f(b)) を結ぶ直線と x軸の交点 $c = ($a * f($b) - $b * f($a)) / (f($b) - f($a)); printf("%12.10f\t%13.10f\n", $c, $c - sqrt(2)); $fc = f($c); if (abs($fc) < 0.0000000001) break; if ($fc < 0) { # f(c) < 0 であれば, 解は区間 (c, b) の中に存在 $a = $c; } else { # f(c) > 0 であれば, 解は区間 (a, c) の中に存在 $b = $c; } } return $c; } function f($x) { return $x * $x - 2; } ?>
Z:\>php Z:\0902.php 1.3333333333 -0.0808802290 1.4000000000 -0.0142135624 1.4117647059 -0.0024488565 1.4137931034 -0.0004204589 1.4141414141 -0.0000721482 1.4142011834 -0.0000123789 1.4142114385 -0.0000021239 1.4142131980 -0.0000003644 1.4142134999 -0.0000000625 1.4142135516 -0.0000000107 1.4142135605 -0.0000000018 1.4142135621 -0.0000000003 1.4142135623 -0.0000000001 1.4142135624 -0.0000000000 1.4142135624
Python
# coding: Shift_JIS import math def f(x): return x * x - 2.0 def falseposition(a, b): while True: # 点 (a,f(a)) と 点 (b,f(b)) を結ぶ直線と x軸の交点 c = (a * f(b) - b * f(a)) / (f(b) - f(a)) print "%12.10f\t%13.10f" % (c, c - math.sqrt(2)) fc = f(c) if (abs(fc) < 0.0000000001): break if (fc < 0): # f(c) < 0 であれば, 解は区間 (c, b) の中に存在 a = c else: # f(c) > 0 であれば, 解は区間 (a, c) の中に存在 b = c return c a = 1.0 b = 2.0 print "%12.10f" % falseposition(a, b)
Z:\>python Z:\0902.py 1.3333333333 -0.0808802290 1.4000000000 -0.0142135624 1.4117647059 -0.0024488565 1.4137931034 -0.0004204589 1.4141414141 -0.0000721482 1.4142011834 -0.0000123789 1.4142114385 -0.0000021239 1.4142131980 -0.0000003644 1.4142134999 -0.0000000625 1.4142135516 -0.0000000107 1.4142135605 -0.0000000018 1.4142135621 -0.0000000003 1.4142135623 -0.0000000001 1.4142135624 -0.0000000000 1.4142135624
Ruby
include Math def f(x) x * x - 2.0 end def falseposition(a, b) while true # 点 (a,f(a)) と 点 (b,f(b)) を結ぶ直線と x軸の交点 c = (a * f(b) - b * f(a)) / (f(b) - f(a)) printf("%12.10f\t%13.10f\n", c, c - sqrt(2)) fc = f(c) if fc.abs < 0.0000000001 break end if fc < 0 # f(c) < 0 であれば, 解は区間 (c, b) の中に存在 a = c else # f(c) > 0 であれば, 解は区間 (a, c) の中に存在 b = c end end c end a = 1.0 b = 2.0 printf("%12.10f\n", falseposition(a, b))
Z:\>ruby Z:\0902.rb 1.3333333333 -0.0808802290 1.4000000000 -0.0142135624 1.4117647059 -0.0024488565 1.4137931034 -0.0004204589 1.4141414141 -0.0000721482 1.4142011834 -0.0000123789 1.4142114385 -0.0000021239 1.4142131980 -0.0000003644 1.4142134999 -0.0000000625 1.4142135516 -0.0000000107 1.4142135605 -0.0000000018 1.4142135621 -0.0000000003 1.4142135623 -0.0000000001 1.4142135624 -0.0000000000 1.4142135624
Groovy
a = 1 b = 2 printf ("%12.10f\n" , falseposition(a, b)) def falseposition(a, b) { while (true) { // 点 (a,f(a)) と 点 (b,f(b)) を結ぶ直線と x軸の交点 c = (a * f(b) - b * f(a)) / (f(b) - f(a)) printf("%12.10f\t%13.10f\n", c, c - Math.sqrt(2)) fc = f(c) if (Math.abs(fc) < 0.0000000001) break if (fc < 0) { // f(c) < 0 であれば, 解は区間 (c, b) の中に存在 a = c } else { // f(c) > 0 であれば, 解は区間 (a, c) の中に存在 b = c } } c } def f(x) { x * x - 2 }
Z:\>groovy Groovy0902.groovy 1.3333333333 -0.0808802291 1.4000000000 -0.0142135624 1.4117647059 -0.0024488565 1.4137931034 -0.0004204589 1.4141414141 -0.0000721482 1.4142011834 -0.0000123789 1.4142114385 -0.0000021239 1.4142131980 -0.0000003644 1.4142134999 -0.0000000625 1.4142135516 -0.0000000107 1.4142135605 -0.0000000018 1.4142135621 -0.0000000003 1.4142135623 -0.0000000001 1.4142135624 -0.0000000000 1.4142135624
Pascal
program Pas0902(arg); {$MODE delphi} uses SysUtils, Math; function f(x:Double):Double; begin result := x * x - 2.0; end; function falseposition(a:Double; b:Double):Double; var c: Double; fc: Double; begin while true do begin { 点 (a,f(a)) と 点 (b,f(b)) を結ぶ直線と x軸の交点 } c := (a * f(b) - b * f(a)) / (f(b) - f(a)); writeln(format('%12.10f'#9'%13.10f', [c, c - Sqrt(2)])); fc := f(c); if Abs(fc) < 0.0000000001 then break; if fc < 0 then begin { f(c) < 0 であれば, 解は区間 (c, b) の中に存在 } a := c; end else begin { f(c) > 0 であれば, 解は区間 (a, c) の中に存在 } b := c; end; end; result := c; end; var a: Double = 1.0; b: Double = 2.0; begin writeln(format('%12.10f', [falseposition(a, b)])); end.
Z:\>fpc -v0 -l- Pas0902.pp Z:\>Pas0902 1.3333333333 -0.0808802290 1.4000000000 -0.0142135624 1.4117647059 -0.0024488565 1.4137931034 -0.0004204589 1.4141414141 -0.0000721482 1.4142011834 -0.0000123789 1.4142114385 -0.0000021239 1.4142131980 -0.0000003644 1.4142134999 -0.0000000625 1.4142135516 -0.0000000107 1.4142135605 -0.0000000018 1.4142135621 -0.0000000003 1.4142135623 -0.0000000001 1.4142135624 0.0000000000 1.4142135624
Ada
with TEXT_IO, Ada.Long_Float_Text_IO, Ada.Numerics.Long_Elementary_Functions; use TEXT_IO, Ada.Long_Float_Text_IO, Ada.Numerics.Long_Elementary_Functions; procedure Ada0902 is function f(x:Long_Float) return Long_Float is begin return x * x - 2.0; end f; function falseposition(x0:Long_Float; x1:Long_Float) return Long_Float is a: Long_Float; b: Long_Float; c: Long_Float; fc: Long_Float; begin a := x0; b := x1; while true loop -- 点 (a,f(a)) と 点 (b,f(b)) を結ぶ直線と x軸の交点 c := (a * f(b) - b * f(a)) / (f(b) - f(a)); Put(c, Fore=>2, Aft=>10, Exp=>0); Put(Ascii.HT); Put(c - Sqrt(2.0), Fore=>2, Aft=>10, Exp=>0); New_Line; fc := f(c); if Abs(fc) < 0.0000000001 then exit; end if; if fc < 0.0 then -- f(c) < 0 であれば, 解は区間 (c, b) の中に存在 a := c; else -- f(c) > 0 であれば, 解は区間 (a, c) の中に存在 b := c; end if; end loop; return c; end falseposition; a: Long_Float := 1.0; b: Long_Float := 2.0; begin Put(falseposition(a, b), Fore=>2, Aft=>10, Exp=>0); New_Line; end Ada0902;
xxxxxx@yyyyyy /Z $ gnatmake Ada0902.adb xxxxxx@yyyyyy /Z $ Ada0902 1.3333333333 -0.0808802290 1.4000000000 -0.0142135624 1.4117647059 -0.0024488565 1.4137931034 -0.0004204589 1.4141414141 -0.0000721482 1.4142011834 -0.0000123789 1.4142114385 -0.0000021239 1.4142131980 -0.0000003644 1.4142134999 -0.0000000625 1.4142135516 -0.0000000107 1.4142135605 -0.0000000018 1.4142135621 -0.0000000003 1.4142135623 -0.0000000001 1.4142135624 -0.0000000000 1.4142135624
VB.NET
Option Explicit Module VB0902 Public Sub Main() Dim a As Double = 1.0 Dim b As Double = 2.0 Console.WriteLine(String.Format("{0,12:F10}", falseposition(a, b))) End Sub Private Function falseposition(ByVal a As Double, ByVal b As Double) Dim c As Double Do While(True) '点 (a,f(a)) と 点 (b,f(b)) を結ぶ直線と x軸の交点 c = (a * f(b) - b * f(a)) / (f(b) - f(a)) Console.WriteLine(String.Format("{0,12:F10}{2}{1,13:F10}", c, c - Math.Sqrt(2), vbTab)) Dim fc As Double = f(c) If Math.Abs(fc) < 0.0000000001 Then Exit Do If fc < 0 Then 'f(c) < 0 であれば, 解は区間 (c, b) の中に存在 a = c Else 'f(c) > 0 であれば, 解は区間 (a, c) の中に存在 b = c End If Loop Return c End Function Private Function f(ByVal x As Double) As Double Return x * x - 2.0 End Function End Module
Z:\>vbc -nologo VB0902.vb Z:\>VB0902 1.3333333333 -0.0808802290 1.4000000000 -0.0142135624 1.4117647059 -0.0024488565 1.4137931034 -0.0004204589 1.4141414141 -0.0000721482 1.4142011834 -0.0000123789 1.4142114385 -0.0000021239 1.4142131980 -0.0000003644 1.4142134999 -0.0000000625 1.4142135516 -0.0000000107 1.4142135605 -0.0000000018 1.4142135621 -0.0000000003 1.4142135623 -0.0000000001 1.4142135624 0.0000000000 1.4142135624
C#
using System; public class CS0902 { public static void Main() { double a = 1; double b = 2; Console.WriteLine(string.Format("{0,12:F10}", falseposition(a, b))); } private static double falseposition(double a, double b) { double c; while (true) { // 点 (a,f(a)) と 点 (b,f(b)) を結ぶ直線と x軸の交点 c c = (a * f(b) - b * f(a)) / (f(b) - f(a)); Console.WriteLine(string.Format("{0,12:F10}\t{1,13:F10}", c, c - Math.Sqrt(2))); double fc = f(c); if (Math.Abs(fc) < 0.0000000001) break; if (fc < 0) { // f(c) < 0 であれば, 解は区間 (c, b) の中に存在 a = c; } else { // f(c) > 0 であれば, 解は区間 (a, c) の中に存在 b = c; } } return c; } private static double f(double x) { return x * x - 2; } }
Z:\>csc -nologo CS0902.cs Z:\>CS0902 1.3333333333 -0.0808802290 1.4000000000 -0.0142135624 1.4117647059 -0.0024488565 1.4137931034 -0.0004204589 1.4141414141 -0.0000721482 1.4142011834 -0.0000123789 1.4142114385 -0.0000021239 1.4142131980 -0.0000003644 1.4142134999 -0.0000000625 1.4142135516 -0.0000000107 1.4142135605 -0.0000000018 1.4142135621 -0.0000000003 1.4142135623 -0.0000000001 1.4142135624 0.0000000000 1.4142135624
Java
import static java.lang.System.out; public class Java0902 { public static void main(String []args) { double a = 1; double b = 2; out.println(String.format("%12.10f", falseposition(a, b))); } private static double falseposition(double a, double b) { double c; while (true) { // 点 (a,f(a)) と 点 (b,f(b)) を結ぶ直線と x軸の交点 c = (a * f(b) - b * f(a)) / (f(b) - f(a)); out.println(String.format("%12.10f\t%13.10f", c, c - Math.sqrt(2))); double fc = f(c); if (Math.abs(fc) < 0.0000000001) break; if (fc < 0){ // f(c) < 0 であれば, 解は区間 (c, b) の中に存在 a = c; } else { // f(c) > 0 であれば, 解は区間 (a, c) の中に存在 b = c; } } return c; } private static double f(double x) { return x * x - 2; } }
Z:\>javac Java0902.java Z:\>java Java0902 1.3333333333 -0.0808802290 1.4000000000 -0.0142135624 1.4117647059 -0.0024488565 1.4137931034 -0.0004204589 1.4141414141 -0.0000721482 1.4142011834 -0.0000123789 1.4142114385 -0.0000021239 1.4142131980 -0.0000003644 1.4142134999 -0.0000000625 1.4142135516 -0.0000000107 1.4142135605 -0.0000000018 1.4142135621 -0.0000000003 1.4142135623 -0.0000000001 1.4142135624 -0.0000000000 1.4142135624
C++
#include <iostream> #include <iomanip> #include <math.h> using namespace std; double f(double x) { return x * x - 2; } double falseposition(double a, double b) { double c; while (true) { // 点 (a,f(a)) と 点 (b,f(b)) を結ぶ直線と x軸の交点 c = (a * f(b) - b * f(a)) / (f(b) - f(a)); cout << setw(12) << fixed << setprecision(10) << c << "\t"; cout << setw(13) << fixed << setprecision(10) << c - sqrt(2) << endl; double fc = f(c); if (fabs(fc) < 0.0000000001) break; if (fc < 0) { // f(c) < 0 であれば, 解は区間 (c, b) の中に存在 a = c; } else { // f(c) > 0 であれば, 解は区間 (a, c) の中に存在 b = c; } } return c; } int main() { double a = 1; double b = 2; cout << setw(12) << fixed << setprecision(10) << falseposition(a, b) << endl; return 0; }
Z:\>bcc32 -q CP0902.cpp cp0902.cpp: Z:\>CP0902 1.3333333333 -0.0808802290 1.4000000000 -0.0142135624 1.4117647059 -0.0024488565 1.4137931034 -0.0004204589 1.4141414141 -0.0000721482 1.4142011834 -0.0000123789 1.4142114385 -0.0000021239 1.4142131980 -0.0000003644 1.4142134999 -0.0000000625 1.4142135516 -0.0000000107 1.4142135605 -0.0000000018 1.4142135621 -0.0000000003 1.4142135623 -0.0000000001 1.4142135624 -0.0000000000 1.4142135624
Objective-C
#import <Foundation/Foundation.h> #import <math.h> double f(double x) { return x * x - 2; } double falseposition(double a, double b) { double c; while (YES) { // 点 (a,f(a)) と 点 (b,f(b)) を結ぶ直線と x軸の交点 c = (a * f(b) - b * f(a)) / (f(b) - f(a)); printf("%12.10f\t%13.10f\n", c, c - sqrt(2)); double fc = f(c); if (fabs(fc) < 0.0000000001) break; if (fc < 0) { // f(c) < 0 であれば, 解は区間 (c, b) の中に存在 a = c; } else { // f(c) > 0 であれば, 解は区間 (a, c) の中に存在 b = c; } } return c; } int main() { double a = 1; double b = 2; printf("%12.10f\n", falseposition(a, b)); return 0; }
xxxxxx@yyyyyy /Z $ gcc -o OC0902 OC0902.m -lobjc -lgnustep-base -I $INCLUDE -L $LIB $CFLAGS xxxxxx@yyyyyy /Z $ OC0902 1.3333333333 -0.0808802290 1.4000000000 -0.0142135624 1.4117647059 -0.0024488565 1.4137931034 -0.0004204589 1.4141414141 -0.0000721482 1.4142011834 -0.0000123789 1.4142114385 -0.0000021239 1.4142131980 -0.0000003644 1.4142134999 -0.0000000625 1.4142135516 -0.0000000107 1.4142135605 -0.0000000018 1.4142135621 -0.0000000003 1.4142135623 -0.0000000001 1.4142135624 -0.0000000000 1.4142135624
D
import std.stdio; import std.math; void main(string[] args) { double a = 1; double b = 2; writefln("%12.10f", falseposition(a, b)); } double falseposition(double a, double b) { double c; while (true) { // 点 (a,f(a)) と 点 (b,f(b)) を結ぶ直線と x軸の交点 c = (a * f(b) - b * f(a)) / (f(b) - f(a)); writefln("%12.10f\t%13.10f", c, c - sqrt(2.0)); double fc = f(c); if (fabs(fc) < 0.0000000001) break; if (fc < 0) { // f(c) < 0 であれば, 解は区間 (c, b) の中に存在 a = c; } else { // f(c) > 0 であれば, 解は区間 (a, c) の中に存在 b = c; } } return c; } double f(double x) { return x * x - 2; }
Z:\>dmd D0902.d Z:\>D0902 1.3333333333 -0.0808802290 1.4000000000 -0.0142135623 1.4117647059 -0.0024488564 1.4137931034 -0.0004204589 1.4141414141 -0.0000721482 1.4142011834 -0.0000123789 1.4142114385 -0.0000021238 1.4142131980 -0.0000003644 1.4142134999 -0.0000000625 1.4142135516 -0.0000000107 1.4142135605 -0.0000000018 1.4142135621 -0.0000000003 1.4142135623 -0.0000000000 1.4142135624 -0.0000000000 1.4142135624
Go
package main import "fmt" import "math" func main() { var a float64 = 1 var b float64 = 2 fmt.Printf("%12.10f\n", falseposition(a, b)) } func falseposition(a float64, b float64) float64 { var c float64 for { // 点 (a,f(a)) と 点 (b,f(b)) を結ぶ直線と x軸の交点 c = (a * f(b) - b * f(a)) / (f(b) - f(a)) fmt.Printf("%12.10f\t%13.10f\n", c, c - math.Sqrt(2)) var fc float64 = f(c) if math.Fabs(fc) < 0.0000000001 { break } if fc < 0 { // f(c) < 0 であれば, 解は区間 (c, b) の中に存在 a = c } else { // f(c) > 0 であれば, 解は区間 (a, c) の中に存在 b = c } } return c } func f(x float64) float64 { return x * x - 2 }
Z:\>8g GO0902.go Z:\>8l -o GO0902.exe GO0902.8 Z:\>GO0902 1.3333333333 -0.0808802290 1.4000000000 -0.0142135624 1.4117647059 -0.0024488565 1.4137931034 -0.0004204589 1.4141414141 -0.0000721482 1.4142011834 -0.0000123789 1.4142114385 -0.0000021239 1.4142131980 -0.0000003644 1.4142134999 -0.0000000625 1.4142135516 -0.0000000107 1.4142135605 -0.0000000018 1.4142135621 -0.0000000003 1.4142135623 -0.0000000001 1.4142135624 -0.0000000000 1.4142135624
Scala
object Scala0902 { def main(args: Array[String]) { val a = 1.0 val b = 2.0 println("%12.10f".format(falseposition(a, b))) } def falseposition(a:Double, b:Double):Double = { // 点 (a,f(a)) と 点 (b,f(b)) を結ぶ直線と x軸の交点 val c = (a * f(b) - b * f(a)) / (f(b) - f(a)) println("%12.10f\t%13.10f".format(c, c - Math.sqrt(2))) val fc = f(c) if (Math.abs(fc) < 0.0000000001) c else { if (fc < 0) { // f(c) < 0 であれば, 解は区間 (c, b) の中に存在 falseposition(c, b) } else { // f(c) > 0 であれば, 解は区間 (a, c) の中に存在 falseposition(a, c) } } } def f(x:Double) = { x * x - 2 } }
Z:\>scala Scala0902.scala 1.3333333333 -0.0808802290 1.4000000000 -0.0142135624 1.4117647059 -0.0024488565 1.4137931034 -0.0004204589 1.4141414141 -0.0000721482 1.4142011834 -0.0000123789 1.4142114385 -0.0000021239 1.4142131980 -0.0000003644 1.4142134999 -0.0000000625 1.4142135516 -0.0000000107 1.4142135605 -0.0000000018 1.4142135621 -0.0000000003 1.4142135623 -0.0000000001 1.4142135624 -0.0000000000 1.4142135624
F#
module Fs0902 open System let f (x:double):double = x * x - 2.0 let rec falseposition (a:double) (b:double):double = // 点 (a,f(a)) と 点 (b,f(b)) を結ぶ直線と x軸の交点 let c = (a * f(b) - b * f(a)) / (f(b) - f(a)) printfn "%12.10f\t%13.10f" c (c - Math.Sqrt(2.0)) let fc = f c if abs(fc) < 0.0000000001 then c else if fc < 0.0 then // f(c) < 0 であれば, 解は区間 (c, b) の中に存在 falseposition c b else // f(c) > 0 であれば, 解は区間 (a, c) の中に存在 falseposition a c let a = 1.0 let b = 2.0 printfn "%12.10f" (falseposition a b) exit 0
Z:\>fsi --nologo --quiet Fs0902.fs 1.3333333333 -0.0808802290 1.4000000000 -0.0142135624 1.4117647059 -0.0024488565 1.4137931034 -0.0004204589 1.4141414141 -0.0000721482 1.4142011834 -0.0000123789 1.4142114385 -0.0000021239 1.4142131980 -0.0000003644 1.4142134999 -0.0000000625 1.4142135516 -0.0000000107 1.4142135605 -0.0000000018 1.4142135621 -0.0000000003 1.4142135623 -0.0000000001 1.4142135624 0.0000000000 1.4142135624
Clojure
(defn f[x] (- (* x x) 2.0)) (defn falseposition [a b] ; 点 (a,f(a)) と 点 (b,f(b)) を結ぶ直線と x軸の交点 (def c (/ (- (* a (f b)) (* b (f a))) (- (f b) (f a)))) (println (format "%12.10f\t%13.10f" c (- c (Math/sqrt 2)))) (def fc (f c)) (if (< (. Math abs fc) 0.00000000001) c (if (< fc 0) (falseposition c b) (falseposition a c)))) (def a 1.0) (def b 2.0) (println (format "%12.10f" (falseposition a b)))
Z:\>java -cp C:\ProgramFiles\clojure-1.5.1\clojure-1.5.1.jar clojure.main Clj0902.clj 1.3333333333 -0.0808802290 1.4000000000 -0.0142135624 1.4117647059 -0.0024488565 1.4137931034 -0.0004204589 1.4141414141 -0.0000721482 1.4142011834 -0.0000123789 1.4142114385 -0.0000021239 1.4142131980 -0.0000003644 1.4142134999 -0.0000000625 1.4142135516 -0.0000000107 1.4142135605 -0.0000000018 1.4142135621 -0.0000000003 1.4142135623 -0.0000000001 1.4142135624 -0.0000000000 1.4142135624 -0.0000000000 1.4142135624
Haskell
import Text.Printf import Debug.Trace f::Double->Double f x = x * x - 2.0 falseposition::Double->Double->Double falseposition a b = let -- 点 (a,f(a)) と 点 (b,f(b)) を結ぶ直線と x軸の交点 c = (a * (f b) - b * (f a)) / ((f b) - (f a)) fc = (f c) :: Double in if abs(fc) < 0.0000000001 then c else if fc < 0.0 then -- f(c) < 0 であれば, 解は区間 (c, b) の中に存在 trace (printf "%12.10f\t%13.10f" c (c - ((sqrt 2.0)::Double))) falseposition c b else -- f(c) > 0 であれば, 解は区間 (a, c) の中に存在 trace (printf "%12.10f\t%13.10f" c (c - ((sqrt 2.0)::Double))) falseposition a c main = do let a = 1.0 let b = 2.0 printf "%12.10f\n" (falseposition a b)
Z:\>runghc Hs0902.hs 1.3333333333 -0.0808802290 1.4000000000 -0.0142135624 1.4117647059 -0.0024488565 1.4137931034 -0.0004204589 1.4141414141 -0.0000721482 1.4142011834 -0.0000123789 1.4142114385 -0.0000021239 1.4142131980 -0.0000003644 1.4142134999 -0.0000000625 1.4142135516 -0.0000000107 1.4142135605 -0.0000000018 1.4142135621 -0.0000000003 1.4142135623 -0.0000000001 1.4142135624