Another update from ingydotnet^djgoku
This commit is contained in:
parent
91df62d461
commit
948b86eafa
7604 changed files with 108452 additions and 22726 deletions
|
|
@ -19,8 +19,8 @@ END FUNCTION
|
|||
FUNCTION midRect(a, b, n)
|
||||
h = (b - a) / n
|
||||
sum = 0
|
||||
FOR x = a TO b - h STEP h
|
||||
sum = sum + (h / 2) * (f(x) + f(x + h))
|
||||
FOR x = a + h / 2 TO b - h / 2 STEP h
|
||||
sum = sum + h * (f(x))
|
||||
NEXT x
|
||||
midRect = sum
|
||||
END FUNCTION
|
||||
|
|
@ -40,7 +40,7 @@ FUNCTION simpson(a, b, n)
|
|||
sum2 = 0
|
||||
|
||||
FOR i = 0 TO n-1
|
||||
sum1 = sum + f(a + h * i + h / 2)
|
||||
sum1 = sum1 + f(a + h * i + h / 2)
|
||||
NEXT i
|
||||
|
||||
FOR i = 1 TO n - 1
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
defmodule Numerical do
|
||||
@funs ~w(leftrect midrect rightrect trapezium simpson)a
|
||||
|
||||
def leftrect(f, left,_right), do: f.(left)
|
||||
def midrect(f, left, right), do: f.((left+right)/2)
|
||||
def rightrect(f,_left, right), do: f.(right)
|
||||
def trapezium(f, left, right), do: (f.(left)+f.(right))/2
|
||||
def simpson(f, left, right), do: (f.(left) + 4*f.((left+right)/2.0) + f.(right)) / 6.0
|
||||
|
||||
def integrate(f, a, b, steps) when is_integer(steps) do
|
||||
delta = (b - a) / steps
|
||||
Enum.each(@funs, fn fun ->
|
||||
total = Enum.reduce(0..steps-1, 0, fn i, acc ->
|
||||
left = a + delta * i
|
||||
acc + apply(Numerical, fun, [f, left, left+delta])
|
||||
end)
|
||||
:io.format "~10s : ~.6f~n", [fun, total * delta]
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
f1 = fn x -> x * x * x end
|
||||
IO.puts "f(x) = x^3, where x is [0,1], with 100 approximations."
|
||||
Numerical.integrate(f1, 0, 1, 100)
|
||||
|
||||
f2 = fn x -> 1 / x end
|
||||
IO.puts "\nf(x) = 1/x, where x is [1,100], with 1,000 approximations. "
|
||||
Numerical.integrate(f2, 1, 100, 1000)
|
||||
|
||||
f3 = fn x -> x end
|
||||
IO.puts "\nf(x) = x, where x is [0,5000], with 5,000,000 approximations."
|
||||
Numerical.integrate(f3, 0, 5000, 5_000_000)
|
||||
|
||||
f4 = fn x -> x end
|
||||
IO.puts "\nf(x) = x, where x is [0,6000], with 6,000,000 approximations."
|
||||
Numerical.integrate(f4, 0, 6000, 6_000_000)
|
||||
|
|
@ -39,35 +39,35 @@ var methods = []method{
|
|||
}
|
||||
|
||||
func rectLeft(t spec) float64 {
|
||||
parts := make([]float64, t.n)
|
||||
var a adder
|
||||
r := t.upper - t.lower
|
||||
nf := float64(t.n)
|
||||
x0 := t.lower
|
||||
for i := range parts {
|
||||
for i := 0; i < t.n; i++ {
|
||||
x1 := t.lower + float64(i+1)*r/nf
|
||||
// x1-x0 better than r/nf.
|
||||
// (with r/nf, the represenation error accumulates)
|
||||
parts[i] = t.f(x0) * (x1 - x0)
|
||||
a.add(t.f(x0) * (x1 - x0))
|
||||
x0 = x1
|
||||
}
|
||||
return sum(parts)
|
||||
return a.total()
|
||||
}
|
||||
|
||||
func rectRight(t spec) float64 {
|
||||
parts := make([]float64, t.n)
|
||||
var a adder
|
||||
r := t.upper - t.lower
|
||||
nf := float64(t.n)
|
||||
x0 := t.lower
|
||||
for i := range parts {
|
||||
for i := 0; i < t.n; i++ {
|
||||
x1 := t.lower + float64(i+1)*r/nf
|
||||
parts[i] = t.f(x1) * (x1 - x0)
|
||||
a.add(t.f(x1) * (x1 - x0))
|
||||
x0 = x1
|
||||
}
|
||||
return sum(parts)
|
||||
return a.total()
|
||||
}
|
||||
|
||||
func rectMid(t spec) float64 {
|
||||
parts := make([]float64, t.n)
|
||||
var a adder
|
||||
r := t.upper - t.lower
|
||||
nf := float64(t.n)
|
||||
// there's a tiny gloss in the x1-x0 trick here. the correct way
|
||||
|
|
@ -77,80 +77,72 @@ func rectMid(t spec) float64 {
|
|||
// reuse the midpoint x's, knowing that they will average out just
|
||||
// as well. we just need one extra point, so we use lower-.5.
|
||||
x0 := t.lower - .5*r/nf
|
||||
for i := range parts {
|
||||
for i := 0; i < t.n; i++ {
|
||||
x1 := t.lower + (float64(i)+.5)*r/nf
|
||||
parts[i] = t.f(x1) * (x1 - x0)
|
||||
a.add(t.f(x1) * (x1 - x0))
|
||||
x0 = x1
|
||||
}
|
||||
return sum(parts)
|
||||
return a.total()
|
||||
}
|
||||
|
||||
func trap(t spec) float64 {
|
||||
parts := make([]float64, t.n)
|
||||
var a adder
|
||||
r := t.upper - t.lower
|
||||
nf := float64(t.n)
|
||||
x0 := t.lower
|
||||
f0 := t.f(x0)
|
||||
for i := range parts {
|
||||
for i := 0; i < t.n; i++ {
|
||||
x1 := t.lower + float64(i+1)*r/nf
|
||||
f1 := t.f(x1)
|
||||
parts[i] = (f0 + f1) * .5 * (x1 - x0)
|
||||
a.add((f0 + f1) * .5 * (x1 - x0))
|
||||
x0, f0 = x1, f1
|
||||
}
|
||||
return sum(parts)
|
||||
return a.total()
|
||||
}
|
||||
|
||||
func simpson(t spec) float64 {
|
||||
parts := make([]float64, 2*t.n+1)
|
||||
var a adder
|
||||
r := t.upper - t.lower
|
||||
nf := float64(t.n)
|
||||
// similar to the rectangle midpoint logic explained above,
|
||||
// we play a little loose with the values used for dx and dx0.
|
||||
dx0 := r / nf
|
||||
parts[0] = t.f(t.lower) * dx0
|
||||
parts[1] = t.f(t.lower+dx0*.5) * dx0 * 4
|
||||
a.add(t.f(t.lower) * dx0)
|
||||
a.add(t.f(t.lower+dx0*.5) * dx0 * 4)
|
||||
x0 := t.lower + dx0
|
||||
for i := 1; i < t.n; i++ {
|
||||
x1 := t.lower + float64(i+1)*r/nf
|
||||
xmid := (x0 + x1) * .5
|
||||
dx := x1 - x0
|
||||
parts[2*i] = t.f(x0) * dx * 2
|
||||
parts[2*i+1] = t.f(xmid) * dx * 4
|
||||
a.add(t.f(x0) * dx * 2)
|
||||
a.add(t.f(xmid) * dx * 4)
|
||||
x0 = x1
|
||||
}
|
||||
parts[2*t.n] = t.f(t.upper) * dx0
|
||||
return sum(parts) / 6
|
||||
a.add(t.f(t.upper) * dx0)
|
||||
return a.total() / 6
|
||||
}
|
||||
|
||||
// sum a list of numbers avoiding loss of precision
|
||||
func sum(v []float64) float64 {
|
||||
if len(v) == 0 {
|
||||
return 0
|
||||
var a adder
|
||||
for _, e := range v {
|
||||
a.add(e)
|
||||
}
|
||||
var parts []float64
|
||||
for _, x := range v {
|
||||
var i int
|
||||
for _, p := range parts {
|
||||
sum := p + x
|
||||
var err float64
|
||||
if math.Abs(x) < math.Abs(p) {
|
||||
err = x - (sum - p)
|
||||
} else {
|
||||
err = p - (sum - x)
|
||||
}
|
||||
if err != 0 {
|
||||
parts[i] = err
|
||||
i++
|
||||
}
|
||||
x = sum
|
||||
}
|
||||
parts = append(parts[:i], x)
|
||||
}
|
||||
var sum float64
|
||||
for _, x := range parts {
|
||||
sum += x
|
||||
}
|
||||
return sum
|
||||
return a.total()
|
||||
}
|
||||
|
||||
type adder struct {
|
||||
sum, e float64
|
||||
}
|
||||
|
||||
func (a *adder) total() float64 {
|
||||
return a.sum + a.e
|
||||
}
|
||||
|
||||
func (a *adder) add(x float64) {
|
||||
sum := a.sum + x
|
||||
e := sum - a.sum
|
||||
a.e += a.sum - (sum - e) + (x - e)
|
||||
a.sum = sum
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
sub leftrect(&f, $a, $b, $n) {
|
||||
my $h = ($b - $a) / $n;
|
||||
$h * [+] do f($_) for $a, *+$h ... $b-$h;
|
||||
$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, *+$h ... $b;
|
||||
$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, *+$h ... $b-$h/2;
|
||||
$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;
|
||||
$h / 2 * [+] f($a), f($b), do f($_) * 2 for $a+$h, *+$h ... $b-$h;
|
||||
$h / 2 * [+] f($a), f($b), |do f($_) * 2 for $a+$h, $a+$h+$h ... $b-$h;
|
||||
}
|
||||
|
||||
sub simpsons(&f, $a, $b, $n) {
|
||||
|
|
@ -33,7 +33,7 @@ sub simpsons(&f, $a, $b, $n) {
|
|||
|
||||
sub tryem($f, $a, $b, $n, $exact) {
|
||||
say "\n$f\n in [$a..$b] / $n";
|
||||
eval "my &f = $f;
|
||||
EVAL "my &f = $f;
|
||||
say ' exact result: ', $exact;
|
||||
say ' rectangle method left: ', leftrect &f, $a, $b, $n;
|
||||
say ' rectangle method right: ', rightrect &f, $a, $b, $n;
|
||||
|
|
@ -46,6 +46,6 @@ tryem '{ $_ ** 3 }', 0, 1, 100, 0.25;
|
|||
|
||||
tryem '1 / *', 1, 100, 1000, log(100);
|
||||
|
||||
tryem '{$_}', 0, 5_000, 10_000, 12_500_000;
|
||||
tryem '*.self', 0, 5_000, 5_000_000, 12_500_000;
|
||||
|
||||
tryem '{$_}', 0, 6_000, 12_000, 18_000_000;
|
||||
tryem '*.self', 0, 6_000, 6_000_000, 18_000_000;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
exact result: 0.25
|
||||
rectangle method left: 0.245025
|
||||
rectangle method right: 0.255025
|
||||
rectangle method mid: 0.2499875
|
||||
rectangle method mid: 0.249988
|
||||
composite trapezoidal rule: 0.250025
|
||||
quadratic simpsons rule: 0.25
|
||||
|
||||
|
|
@ -16,20 +16,20 @@ composite trapezoidal rule: 0.250025
|
|||
composite trapezoidal rule: 4.60598605751468
|
||||
quadratic simpsons rule: 4.60517038495714
|
||||
|
||||
{$_}
|
||||
in [0..5000] / 10000
|
||||
*.self
|
||||
in [0..5000] / 5000000
|
||||
exact result: 12500000
|
||||
rectangle method left: 12498750
|
||||
rectangle method right: 12501250
|
||||
rectangle method left: 12499997.5
|
||||
rectangle method right: 12500002.5
|
||||
rectangle method mid: 12500000
|
||||
composite trapezoidal rule: 12500000
|
||||
quadratic simpsons rule: 12500000
|
||||
|
||||
{$_}
|
||||
in [0..6000] / 12000
|
||||
*.self
|
||||
in [0..6000] / 6000000
|
||||
exact result: 18000000
|
||||
rectangle method left: 17998500
|
||||
rectangle method right: 18001500
|
||||
rectangle method left: 17999997
|
||||
rectangle method right: 18000003
|
||||
rectangle method mid: 18000000
|
||||
composite trapezoidal rule: 18000000
|
||||
quadratic simpsons rule: 18000000
|
||||
|
|
|
|||
|
|
@ -1,59 +1,47 @@
|
|||
/*REXX program numerically integrates using five different methods. */
|
||||
numeric digits 20 /*use twenty digits precision. */
|
||||
/*REXX program does numerical integration using five different algorithms.*/
|
||||
numeric digits 20 /*use twenty decimal digits precision. */
|
||||
|
||||
do test=1 for 4 /*perform the test suite. */
|
||||
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,79,'─') /*display a header for the test. */
|
||||
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)
|
||||
say ' simpson('L","H','i") = " simpson(L,H,i)
|
||||
say ' trapezoid('L","H','i") = " trapezoid(L,H,i)
|
||||
end /*test*/
|
||||
exit /*stick a fork in it, we're done.*/
|
||||
/*──────────────────────────────────LEFT_RECT subroutine────────────────*/
|
||||
left_rect: procedure expose test; parse arg a,b,n; h=(b-a)/n
|
||||
sum=0
|
||||
do x=a by h for n
|
||||
sum=sum+f(x)
|
||||
end /*x*/
|
||||
return sum*h
|
||||
/*──────────────────────────────────MIDPOINT_RECT subroutine────────────*/
|
||||
midpoint_rect: procedure expose test; parse arg a,b,n; h=(b-a)/n
|
||||
sum=0
|
||||
do x=a+h/2 by h for n
|
||||
sum=sum+f(x)
|
||||
end /*x*/
|
||||
return sum*h
|
||||
/*──────────────────────────────────RIGHT_RECT subroutine───────────────*/
|
||||
right_rect: procedure expose test; parse arg a,b,n; h=(b-a)/n
|
||||
sum=0
|
||||
do x=a+h by h for n
|
||||
sum=sum+f(x)
|
||||
end /*x*/
|
||||
return sum*h
|
||||
/*──────────────────────────────────SIMPSON subroutine──────────────────*/
|
||||
simpson: procedure expose test; parse arg a,b,n; h=(b-a)/n
|
||||
sum1=f(a+h/2)
|
||||
sum2=0; do x=1 to n-1
|
||||
sum1=sum1+f(a+h*x+h*.5)
|
||||
sum2=sum2+f(a+x*h)
|
||||
end /*x*/
|
||||
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
|
||||
say
|
||||
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)
|
||||
say ' Simpson('L", "H', 'i") ──► " Simpson(L, H, i)
|
||||
say ' trapezium('L", "H', 'i") ──► " trapezium(L, H, i)
|
||||
end /*test*/
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*────────────────────────────────────────────────────────────────────────────*/
|
||||
f: if test==1 then return arg(1)**3
|
||||
if test==2 then return 1/arg(1)
|
||||
return arg(1)
|
||||
/*────────────────────────────────────────────────────────────────────────────*/
|
||||
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 /*return the number with no trailing 0s*/
|
||||
/*────────────────────────────────────────────────────────────────────────────*/
|
||||
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 /*return the number with no trailing 0s*/
|
||||
/*────────────────────────────────────────────────────────────────────────────*/
|
||||
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 /*return the number with no trailing 0s*/
|
||||
/*────────────────────────────────────────────────────────────────────────────*/
|
||||
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*sum1+2*sum2)/6
|
||||
/*──────────────────────────────────TRAPEZOID subroutine────────────────*/
|
||||
trapezoid: procedure expose test; parse arg a,b,n; h=(b-a)/n
|
||||
sum=0
|
||||
do x=a to b by h
|
||||
sum=sum+h*(f(x)+f(x+h))*.5
|
||||
end /*x*/
|
||||
return sum
|
||||
/*──────────────────────────────────F subroutine────────────────────────*/
|
||||
f: procedure expose test; parse arg z
|
||||
if test==1 then return z**3
|
||||
if test==2 then return 1/z
|
||||
return z
|
||||
return h*(f(a) + f(b) + 4*$ + 2*@)/6 /*return the number with no trailing 0s*/
|
||||
/*────────────────────────────────────────────────────────────────────────────*/
|
||||
trapezium: procedure expose test; parse arg a,b,n; h=(b-a)/n
|
||||
$=0
|
||||
do x=a by h for n; $=$+(f(x)+f(x+h)); end /*x*/
|
||||
return $*h/2 /*return the number with no trailing 0s*/
|
||||
|
|
|
|||
20
Task/Numerical-integration/Rust/numerical-integration.rust
Normal file
20
Task/Numerical-integration/Rust/numerical-integration.rust
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
fn integral<F>(f: F, range: std::ops::Range<f64>, n_steps: u32) -> f64
|
||||
where F: Fn(f64) -> f64
|
||||
{
|
||||
let step_size = (range.end - range.start)/n_steps as f64;
|
||||
|
||||
let mut integral = (f(range.start) + f(range.end))/2.;
|
||||
let mut pos = range.start + step_size;
|
||||
while pos < range.end {
|
||||
integral += f(pos);
|
||||
pos += step_size;
|
||||
}
|
||||
integral * step_size
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("{}", integral(|x| x.powi(3), 0.0..1.0, 100));
|
||||
println!("{}", integral(|x| 1.0/x, 1.0..100.0, 1000));
|
||||
println!("{}", integral(|x| x, 0.0..5000.0, 5_000_000));
|
||||
println!("{}", integral(|x| x, 0.0..6000.0, 6_000_000));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue