September Morn Update

This commit is contained in:
Ingy döt Net 2019-09-12 10:33:56 -07:00
parent 4e2d22a71d
commit aac6731f2c
6856 changed files with 141342 additions and 21127 deletions

View file

@ -1,38 +1,43 @@
Write functions to calculate the definite integral of a function &nbsp; &nbsp; <big><big> <span style="font-family: serif">''ƒ(x)''</span> </big></big> &nbsp; &nbsp; using &nbsp; ''all'' &nbsp; five of the following methods:
::* &nbsp; [[wp:Rectangle_method|rectangular]]
::::* &nbsp; left
::::* &nbsp; right
::::* &nbsp; midpoint
::* &nbsp; [[wp:Trapezoidal_rule|trapezium]]
::* &nbsp; [[wp:Simpson%27s_rule|Simpson's]]
Write functions to calculate the definite integral of a function <big><big> {{math|1=''ƒ(x)''}} </big></big> using ''all'' five of the following methods:
:* [[wp:Rectangle_method|rectangular]]
:** left
:** right
:** midpoint
:* [[wp:Trapezoidal_rule|trapezium]]
:* [[wp:Simpson%27s_rule|Simpson's]]
:** composite
<br>
Your functions should take in the upper and lower bounds &nbsp; (<span style="font-family: serif">''a''</span> &nbsp; and &nbsp; <span style="font-family: serif">''b''</span>), &nbsp; and the number of approximations to make in that range &nbsp; (<span style="font-family: serif">''n''</span>).
Your functions should take in the upper and lower bounds ({{math|''a''}} and {{math|''b''}}), and the number of approximations to make in that range ({{math|''n''}}).
Assume that your example already has a function that gives values for &nbsp; &nbsp; <big> <span style="font-family: serif">''ƒ(x)''</span>. </big>
Assume that your example already has a function that gives values for <big> {{math|1=''ƒ(x)''}} </big>.
Simpson's method is defined by the following pseudo-code:
<pre>
h := (b - a) / n
sum1 := f(a + h/2)
sum2 := 0
{| class="mw-collapsible mw-collapsed"
|+ Pseudocode: Simpson's method, composite
|-
|
'''procedure''' quad_simpson_composite(f, a, b, n)
h := (b - a) / n
sum1 := f(a + h/2)
sum2 := 0
loop on i from 1 to (n - 1)
sum1 := sum1 + f(a + h * i + h/2)
sum2 := sum2 + f(a + h * i)
loop on i from 1 to (n - 1)
sum1 := sum1 + f(a + h * i + h/2)
sum2 := sum2 + f(a + h * i)
''answer'' := (h / 6) * (f(a) + f(b) + 4*sum1 + 2*sum2)
|}
answer := (h / 6) * (f(a) + f(b) + 4*sum1 + 2*sum2)
</pre>
Demonstrate your function by showing the results for:
* <big> ƒ(x) = x<sup>3</sup>, </big> &nbsp; where &nbsp; &nbsp; '''x''' &nbsp; &nbsp; is &nbsp; [0,1], &nbsp; with 100 approximations. &nbsp; The exact result is &nbsp; 1/4, &nbsp; or &nbsp; 0.25.
* <big> ƒ(x) = 1/x, </big> &nbsp; where &nbsp; '''x''' &nbsp; is &nbsp; [1,100], &nbsp; with 1,000 approximations. &nbsp; The exact result is the natural log of 100, &nbsp; or about &nbsp; 4.605170
* <big> ƒ(x) = x, </big> &nbsp; &nbsp; where &nbsp; '''x''' &nbsp; is &nbsp; [0,5000], &nbsp; with 5,000,000 approximations. &nbsp; The exact result is &nbsp; 12,500,000.
* <big> ƒ(x) = x, </big> &nbsp; &nbsp; where &nbsp; '''x''' &nbsp; is &nbsp; [0,6000], &nbsp; with 6,000,000 approximations. &nbsp; The exact result is &nbsp; 18,000,000.
* {{math|1=ƒ(x) = x<sup>3</sup>}}, where '''x''' is [0,1], with 100 approximations. The exact result is 1/4, or 0.25.
* {{math|1=ƒ(x) = 1/x}}, where '''x''' is [1,100], with 1,000 approximations. The exact result is the natural log of 100, or about 4.605170
* {{math|1=ƒ(x) = x}}, where '''x''' is [0,5000], with 5,000,000 approximations. The exact result is 12,500,000.
* {{math|1=ƒ(x) = x}}, where '''x''' is [0,6000], with 6,000,000 approximations. The exact result is 18,000,000.
<br>
<br/>
'''See also'''
* [[Active object]] for integrating a function of real time.
* [[Numerical integration/Gauss-Legendre Quadrature]] for another integration method.
<br><br>
* [[Special:PrefixIndex/Numerical integration]] for other integration methods.
<br/>

View file

@ -0,0 +1,94 @@
1000 PRINT "F(X)";" FROM";" TO";" L-Rect";" M-Rect";" R-Rect ";" Trapez";" Simpson"
1010 fromval:=0
1020 toval:=1
1030 PRINT "X^3 ";
1040 PRINT USING "#####": fromval;
1050 PRINT USING "#####": toval;
1060 PRINT USING "###.#########": numint(f1, "L", fromval, toval, 100);
1070 PRINT USING "###.#########": numint(f1, "R", fromval, toval, 100);
1080 PRINT USING "###.#########": numint(f1, "M", fromval, toval, 100);
1090 PRINT USING "###.#########": numint(f1, "T", fromval, toval, 100);
1100 PRINT USING "###.#########": numint(f1, "S", fromval, toval, 100)
1110 //
1120 fromval:=1
1130 toval:=100
1140 PRINT "1/X ";
1150 PRINT USING "#####": fromval;
1160 PRINT USING "#####": toval;
1170 PRINT USING "###.#########": numint(f2, "L", fromval, toval, 1000);
1180 PRINT USING "###.#########": numint(f2, "R", fromval, toval, 1000);
1190 PRINT USING "###.#########": numint(f2, "M", fromval, toval, 1000);
1200 PRINT USING "###.#########": numint(f2, "T", fromval, toval, 1000);
1210 PRINT USING "###.#########": numint(f2, "S", fromval, toval, 1000)
1220 fromval:=0
1230 toval:=5000
1240 PRINT "X ";
1250 PRINT USING "#####": fromval;
1260 PRINT USING "#####": toval;
1270 PRINT USING "#########.###": numint(f3, "L", fromval, toval, 5000000);
1280 PRINT USING "#########.###": numint(f3, "R", fromval, toval, 5000000);
1290 PRINT USING "#########.###": numint(f3, "M", fromval, toval, 5000000);
1300 PRINT USING "#########.###": numint(f3, "T", fromval, toval, 5000000);
1310 PRINT USING "#########.###": numint(f3, "S", fromval, toval, 5000000)
1320 //
1330 fromval:=0
1340 toval:=6000
1350 PRINT "X ";
1360 PRINT USING "#####": fromval;
1370 PRINT USING "#####": toval;
1380 PRINT USING "#########.###": numint(f3, "L", fromval, toval, 6000000);
1390 PRINT USING "#########.###": numint(f3, "R", fromval, toval, 6000000);
1400 PRINT USING "#########.###": numint(f3, "M", fromval, toval, 6000000);
1410 PRINT USING "#########.###": numint(f3, "T", fromval, toval, 6000000);
1420 PRINT USING "#########.###": numint(f3, "S", fromval, toval, 6000000)
1430 END
1440 //
1450 FUNC numint(FUNC f, type$, lbound, rbound, iters) CLOSED
1460 delta:=(rbound-lbound)/iters
1470 integral:=0
1480 CASE type$ OF
1490 WHEN "L", "T", "S"
1500 actval:=lbound
1510 WHEN "M"
1520 actval:=lbound+delta/2
1530 WHEN "R"
1540 actval:=lbound+delta
1550 OTHERWISE
1560 actval:=lbound
1570 ENDCASE
1580 FOR n:=0 TO iters-1 DO
1590 CASE type$ OF
1600 WHEN "L", "M", "R"
1610 integral:+f(actval+n*delta)*delta
1620 WHEN "T"
1630 integral:+delta*(f(actval+n*delta)+f(actval+(n+1)*delta))/2
1640 WHEN "S"
1650 IF n=0 THEN
1660 sum1:=f(lbound+delta/2)
1670 sum2:=0
1680 ELSE
1690 sum1:+f(actval+n*delta+delta/2)
1700 sum2:+f(actval+n*delta)
1710 ENDIF
1720 OTHERWISE
1730 integral:=0
1740 ENDCASE
1750 ENDFOR
1760 IF type$="S" THEN
1770 RETURN (delta/6)*(f(lbound)+f(rbound)+4*sum1+2*sum2)
1780 ELSE
1790 RETURN integral
1800 ENDIF
1810 ENDFUNC
1820 //
1830 FUNC f1(x) CLOSED
1840 RETURN x^3
1850 ENDFUNC
1860 //
1870 FUNC f2(x) CLOSED
1880 RETURN 1/x
1890 ENDFUNC
1900 //
1910 FUNC f3(x) CLOSED
1920 RETURN x
1930 ENDFUNC

View file

@ -1,43 +1,71 @@
integrals: procedure options (main);
integrals: procedure options (main); /* 1 September 2019 */
/* The function to be integrated */
f: procedure (x) returns (float);
declare x float;
return (3*x**2 + 2*x);
f: procedure (x, function) returns (float(18));
declare x float(18), function fixed binary;
select (function);
when (1) return (x**3);
when (2) return (1/x);
when (3) return (x);
when (4) return (x);
end;
end f;
declare (a, b) float;
declare (rect_area, trap_area, Simpson) float;
declare (d, dx) fixed decimal (10,2);
declare (l, r) float;
declare (S1, S2) float;
declare (a, b) fixed decimal (10);
declare (rect_area, trap_area, Simpson) float(18);
declare (d, dx) float(18);
declare (S1, S2) float(18);
declare N fixed decimal (15), function fixed binary;
declare k fixed decimal (7,2);
l = 0; r = 5;
a = 0; b = 5; /* bounds of integration */
dx = 0.05;
put (' Rectangle-left Rectangle-mid Rectangle-right' ||
' Trapezoid Simpson');
do function = 1 to 4;
select(function);
when (1) do; N = 100; a = 0; b = 1; end;
when (2) do; N = 1000; a = 1; b = 100; end;
when (3) do; N = 5000000; a = 0; b = 5000; end;
when (4) do; N = 6000000; a = 0; b = 6000; end;
end;
/* Rectangle method */
rect_area = 0;
do d = a to b by dx;
rect_area = rect_area + dx*f(d);
dx = (b-a)/float(N);
/* Rectangle method, left-side */
rect_area = 0;
do d = 0 to N-1;
rect_area = rect_area + dx*f(a + d*dx, function);
end;
put skip edit (rect_area) (E(25, 15));
/* Rectangle method, mid-point */
rect_area = 0;
do d = 0 to N-1;
rect_area = rect_area + dx*f(a + d*dx + dx/2, function);
end;
put edit (rect_area) (E(25, 15));
/* Rectangle method, right-side */
rect_area = 0;
do d = 1 to N;
rect_area = rect_area + dx*f(a + d*dx, function);
end;
put edit (rect_area) (E(25, 15));
/* Trapezoid method */
trap_area = 0;
do d = 0 to N-1;
trap_area = trap_area + dx*(f(a+d*dx, function) + f(a+(d+1)*dx, function))/2;
end;
put edit (trap_area) (X(1), E(25, 15));
/* Simpson's Rule */
S1 = f(a+dx/2, function);
S2 = 0;
do d = 1 to N-1;
S1 = S1 + f(a+d*dx+dx/2, function);
S2 = S2 + f(a+d*dx, function);
end;
Simpson = dx * (f(a, function) + f(b, function) + 4*S1 + 2*S2) / 6;
put edit (Simpson) (X(1), E(25, 15));
end;
put skip data (rect_area);
/* trapezoid method */
trap_area = 0;
do d = a to b by dx;
trap_area = trap_area + dx*(f(d) + f(d+dx))/2;
end;
put skip data (trap_area);
/* Simpson's */
S1 = f(a+dx/2);
S2 = 0;
do d = a to b by dx;
S1 = S1 + f(d+dx+dx/2);
S2 = S2 + f(d+dx);
end;
Simpson = dx * (f(a) + f(b) + 4*S1 + 2*S2) / 6;
put skip data (Simpson);
end integrals;

View file

@ -0,0 +1,59 @@
use MONKEY-SEE-NO-EVAL;
sub leftrect(&f, $a, $b, $n) {
my $h = ($b - $a) / $n;
$h * [+] do f($_) for $a, $a+$h ... $b-$h;
}
sub rightrect(&f, $a, $b, $n) {
my $h = ($b - $a) / $n;
$h * [+] do f($_) for $a+$h, $a+$h+$h ... $b;
}
sub midrect(&f, $a, $b, $n) {
my $h = ($b - $a) / $n;
$h * [+] do f($_) for $a+$h/2, $a+$h+$h/2 ... $b-$h/2;
}
sub trapez(&f, $a, $b, $n) {
my $h = ($b - $a) / $n;
my $partial-sum += f($_) * 2 for $a+$h, $a+$h+$h ... $b-$h;
$h / 2 * [+] f($a), f($b), $partial-sum;
}
sub simpsons(&f, $a, $b, $n) {
my $h = ($b - $a) / $n;
my $h2 = $h/2;
my $sum1 = f($a + $h2);
my $sum2 = 0;
for $a+$h, *+$h ... $b-$h {
$sum1 += f($_ + $h2);
$sum2 += f($_);
}
($h / 6) * (f($a) + f($b) + 4*$sum1 + 2*$sum2);
}
sub integrate($f, $a, $b, $n, $exact) {
my @r0;
my $e = 0.000001;
@r0.push: "$f\n in [$a..$b] / $n\n";
@r0.push: ' exact result: '~ $exact.round($e);
my (@r1,@r2,@r3,@r4,@r5);
my &f;
EVAL "&f = $f";
my $p1 = Promise.start( { @r1.push: ' rectangle method left: '~ leftrect(&f, $a, $b, $n).round($e) } );
my $p2 = Promise.start( { @r2.push: ' rectangle method right: '~ rightrect(&f, $a, $b, $n).round($e) } );
my $p3 = Promise.start( { @r3.push: ' rectangle method mid: '~ midrect(&f, $a, $b, $n).round($e) } );
my $p4 = Promise.start( { @r4.push: 'composite trapezoidal rule: '~ trapez(&f, $a, $b, $n).round($e) } );
my $p5 = Promise.start( { @r5.push: ' quadratic simpsons rule: '~ simpsons(&f, $a, $b, $n).round($e) } );
await $p1, $p2, $p3, $p4, $p5;
@r0, @r1, @r2, @r3, @r4, @r5;
}
.say for integrate '{ $_ ** 3 }', 0, 1, 100, 0.25; say '';
.say for integrate '1 / *', 1, 100, 1000, log(100); say '';
.say for integrate '*.self', 0, 5_000, 5_000_000, 12_500_000; say '';
.say for integrate '*.self', 0, 6_000, 6_000_000, 18_000_000;

View file

@ -0,0 +1,81 @@
use feature 'say';
sub leftrect {
my($func, $a, $b, $n) = @_;
my $h = ($b - $a) / $n;
my $sum = 0;
for ($_ = $a; $_ < $b; $_ += $h) { $sum += $func->($_) }
$h * $sum
}
sub rightrect {
my($func, $a, $b, $n) = @_;
my $h = ($b - $a) / $n;
my $sum = 0;
for ($_ = $a+$h; $_ < $b+$h; $_ += $h) { $sum += $func->($_) }
$h * $sum
}
sub midrect {
my($func, $a, $b, $n) = @_;
my $h = ($b - $a) / $n;
my $sum = 0;
for ($_ = $a + $h/2; $_ < $b; $_ += $h) { $sum += $func->($_) }
$h * $sum
}
sub trapez {
my($func, $a, $b, $n) = @_;
my $h = ($b - $a) / $n;
my $sum = $func->($a) + $func->($b);
for ($_ = $a+$h; $_ < $b; $_ += $h) { $sum += 2 * $func->($_) }
$h/2 * $sum
}
sub simpsons {
my($func, $a, $b, $n) = @_;
my $h = ($b - $a) / $n;
my $h2 = $h/2;
my $sum1 = $func->($a + $h2);
my $sum2 = 0;
for ($_ = $a+$h; $_ < $b; $_ += $h) {
$sum1 += $func->($_ + $h2);
$sum2 += $func->($_);
}
$h/6 * ($func->($a) + $func->($b) + 4*$sum1 + 2*$sum2)
}
# round where needed, display in a reasonable format
sub sig {
my($value) = @_;
my $rounded;
if ($value < 10) {
$rounded = sprintf '%.6f', $value;
$rounded =~ s/(\.\d*[1-9])0+$/$1/;
$rounded =~ s/\.0+$//;
} else {
$rounded = sprintf "%.1f", $value;
$rounded =~ s/\.0+$//;
}
return $rounded;
}
sub integrate {
my($func, $a, $b, $n, $exact) = @_;
my $f = sub { local $_ = shift; eval $func };
my @res;
push @res, "$func\n in [$a..$b] / $n";
push @res, ' exact result: ' . rnd($exact);
push @res, ' rectangle method left: ' . rnd( leftrect($f, $a, $b, $n));
push @res, ' rectangle method right: ' . rnd(rightrect($f, $a, $b, $n));
push @res, ' rectangle method mid: ' . rnd( midrect($f, $a, $b, $n));
push @res, 'composite trapezoidal rule: ' . rnd( trapez($f, $a, $b, $n));
push @res, ' quadratic simpsons rule: ' . rnd( simpsons($f, $a, $b, $n));
@res;
}
say for integrate('$_ ** 3', 0, 1, 100, 0.25); say '';
say for integrate('1 / $_', 1, 100, 1000, log(100)); say '';
say for integrate('$_', 0, 5_000, 5_000_000, 12_500_000); say '';
say for integrate('$_', 0, 6_000, 6_000_000, 18_000_000);

View file

@ -2,12 +2,12 @@
numeric digits 20 /*use twenty decimal digits precision. */
do test=1 for 4 /*perform the 4 different test suites. */
if test==1 then do; L=0; H= 1; i= 100; end
if test==2 then do; L=1; H= 100; i= 1000; end
if test==3 then do; L=0; H=5000; i=5000000; end
if test==4 then do; L=0; H=6000; i=5000000; end
if test==1 then do; L= 0; H= 1; i= 100; end
if test==2 then do; L= 1; H= 100; i= 1000; end
if test==3 then do; L= 0; H= 5000; i= 5000000; end
if test==4 then do; L= 0; H= 6000; i= 5000000; end
say
say center('test' test,65,'') /*display a header for the test suite. */
say center('test' test, 65, "") /*display a header for the test suite. */
say ' left rectangular('L", "H', 'i") ──► " left_rect(L, H, i)
say ' midpoint rectangular('L", "H', 'i") ──► " midpoint_rect(L, H, i)
say ' right rectangular('L", "H', 'i") ──► " right_rect(L, H, i)
@ -16,32 +16,32 @@ numeric digits 20 /*use twenty decimal digits pre
end /*test*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
f: if test==1 then return arg(1)**3 /*choose the cube function. */
if test==2 then return 1/arg(1) /* " " reciprocal " */
f: if test==1 then return arg(1) **3 /*choose the cube function. */
if test==2 then return 1 / arg(1) /* " " reciprocal " */
return arg(1) /* " " "as-is" " */
/*──────────────────────────────────────────────────────────────────────────────────────*/
left_rect: procedure expose test; parse arg a,b,n; h=(b-a)/n
$=0
left_rect: procedure expose test; parse arg a,b,n; h= (b-a) / n
$= 0
do x=a by h for n; $=$+f(x); end /*x*/
return $*h/1
/*──────────────────────────────────────────────────────────────────────────────────────*/
midpoint_rect: procedure expose test; parse arg a,b,n; h=(b-a)/n
$=0
midpoint_rect: procedure expose test; parse arg a,b,n; h= (b-a) / n
$= 0
do x=a+h/2 by h for n; $=$+f(x); end /*x*/
return $*h/1
/*──────────────────────────────────────────────────────────────────────────────────────*/
right_rect: procedure expose test; parse arg a,b,n; h=(b-a)/n
$=0
right_rect: procedure expose test; parse arg a,b,n; h= (b-a) / n
$= 0
do x=a+h by h for n; $=$+f(x); end /*x*/
return $*h/1
/*──────────────────────────────────────────────────────────────────────────────────────*/
Simpson: procedure expose test; parse arg a,b,n; h=(b-a)/n
$=f(a+h/2)
@=0; do x=1 for n-1; $=$+f(a+h*x+h*.5); @=@+f(a+x*h); end /*x*/
Simpson: procedure expose test; parse arg a,b,n; h= (b-a) / n
$= f(a + h/2)
@= 0; do x=1 for n-1; $=$+f(a+h*x+h*.5); @=@+f(a+x*h); end /*x*/
return h*(f(a) + f(b) + 4*$ + 2*@) / 6
/*──────────────────────────────────────────────────────────────────────────────────────*/
trapezium: procedure expose test; parse arg a,b,n; h=(b-a)/n
$=0
$= 0
do x=a by h for n; $=$+(f(x)+f(x+h)); end /*x*/
return $*h/2

View file

@ -0,0 +1,105 @@
public enum IntegrationType : CaseIterable {
case rectangularLeft
case rectangularRight
case rectangularMidpoint
case trapezium
case simpson
}
public func integrate(
from: Double,
to: Double,
n: Int,
using: IntegrationType = .simpson,
f: (Double) -> Double
) -> Double {
let integrationFunc: (Double, Double, Int, (Double) -> Double) -> Double
switch using {
case .rectangularLeft:
integrationFunc = integrateRectL
case .rectangularRight:
integrationFunc = integrateRectR
case .rectangularMidpoint:
integrationFunc = integrateRectMid
case .trapezium:
integrationFunc = integrateTrapezium
case .simpson:
integrationFunc = integrateSimpson
}
return integrationFunc(from, to, n, f)
}
private func integrateRectL(from: Double, to: Double, n: Int, f: (Double) -> Double) -> Double {
let h = (to - from) / Double(n)
var x = from
var sum = 0.0
while x <= to - h {
sum += f(x)
x += h
}
return h * sum
}
private func integrateRectR(from: Double, to: Double, n: Int, f: (Double) -> Double) -> Double {
let h = (to - from) / Double(n)
var x = from
var sum = 0.0
while x <= to - h {
sum += f(x + h)
x += h
}
return h * sum
}
private func integrateRectMid(from: Double, to: Double, n: Int, f: (Double) -> Double) -> Double {
let h = (to - from) / Double(n)
var x = from
var sum = 0.0
while x <= to - h {
sum += f(x + h / 2.0)
x += h
}
return h * sum
}
private func integrateTrapezium(from: Double, to: Double, n: Int, f: (Double) -> Double) -> Double {
let h = (to - from) / Double(n)
var sum = f(from) + f(to)
for i in 1..<n {
sum += 2 * f(from + Double(i) * h)
}
return h * sum / 2
}
private func integrateSimpson(from: Double, to: Double, n: Int, f: (Double) -> Double) -> Double {
let h = (to - from) / Double(n)
var sum1 = 0.0
var sum2 = 0.0
for i in 0..<n {
sum1 += f(from + h * Double(i) + h / 2.0)
}
for i in 1..<n {
sum2 += f(from + h * Double(i))
}
return h / 6.0 * (f(from) + f(to) + 4.0 * sum1 + 2.0 * sum2)
}
let types = IntegrationType.allCases
print("f(x) = x^3:", types.map({ integrate(from: 0, to: 1, n: 100, using: $0, f: { pow($0, 3) }) }))
print("f(x) = 1 / x:", types.map({ integrate(from: 1, to: 100, n: 1000, using: $0, f: { 1 / $0 }) }))
print("f(x) = x, 0 -> 5_000:", types.map({ integrate(from: 0, to: 5_000, n: 5_000_000, using: $0, f: { $0 }) }))
print("f(x) = x, 0 -> 6_000:", types.map({ integrate(from: 0, to: 6_000, n: 6_000_000, using: $0, f: { $0 }) }))