Numerical integration: Difference between revisions
Content added Content deleted
m ('round' defaults to 3) |
(→{{header|Go}}: fix float type per language change) |
||
Line 1,007: | Line 1,007: | ||
end module FunctionHolder</lang> |
end module FunctionHolder</lang> |
||
=={{header|Go}}== |
=={{header|Go}}== |
||
⚫ | |||
The float type used here is 32 bits. |
|||
⚫ | |||
⚫ | |||
import ( |
import ( |
||
Line 1,019: | Line 1,017: | ||
// specification for an integration |
// specification for an integration |
||
type spec struct { |
type spec struct { |
||
lower, upper |
lower, upper float64 // bounds for integration |
||
n int // number of parts |
n int // number of parts |
||
exact |
exact float64 // expected answer |
||
fs string // mathematical description of function |
fs string // mathematical description of function |
||
f func( |
f func(float64) float64 // function to integrate |
||
} |
} |
||
// test cases per task description |
// test cases per task description |
||
var data = []spec{ |
var data = []spec{ |
||
spec{0, 1, 100, .25, "x^3", func(x |
spec{0, 1, 100, .25, "x^3", func(x float64) float64 { return x * x * x }}, |
||
spec{1, 100, 1000, |
spec{1, 100, 1000, float64(math.Log(100)), "1/x", func(x float64) float64 { return 1 / x }}, |
||
spec{0, 5000, 5e5, 12.5e6, "x", func(x |
spec{0, 5000, 5e5, 12.5e6, "x", func(x float64) float64 { return x }}, |
||
spec{0, 6000, 6e6, 18e6, "x", func(x |
spec{0, 6000, 6e6, 18e6, "x", func(x float64) float64 { return x }}, |
||
} |
} |
||
Line 1,037: | Line 1,035: | ||
type method struct { |
type method struct { |
||
name string |
name string |
||
integrate func(spec) |
integrate func(spec) float64 |
||
} |
} |
||
Line 1,049: | Line 1,047: | ||
} |
} |
||
func rectLeft(t spec) |
func rectLeft(t spec) float64 { |
||
parts := make([] |
parts := make([]float64, t.n) |
||
r := t.upper - t.lower |
r := t.upper - t.lower |
||
nf := |
nf := float64(t.n) |
||
x0 := t.lower |
x0 := t.lower |
||
for i := range parts { |
for i := range parts { |
||
x1 := t.lower + |
x1 := t.lower + float64(i+1)*r/nf |
||
// x1-x0 better than r/nf. |
// x1-x0 better than r/nf. |
||
// (with r/nf, the represenation error accumulates) |
// (with r/nf, the represenation error accumulates) |
||
Line 1,064: | Line 1,062: | ||
} |
} |
||
func rectRight(t spec) |
func rectRight(t spec) float64 { |
||
parts := make([] |
parts := make([]float64, t.n) |
||
r := t.upper - t.lower |
r := t.upper - t.lower |
||
nf := |
nf := float64(t.n) |
||
x0 := t.lower |
x0 := t.lower |
||
for i := range parts { |
for i := range parts { |
||
x1 := t.lower + |
x1 := t.lower + float64(i+1)*r/nf |
||
parts[i] = t.f(x1) * (x1 - x0) |
parts[i] = t.f(x1) * (x1 - x0) |
||
x0 = x1 |
x0 = x1 |
||
Line 1,077: | Line 1,075: | ||
} |
} |
||
func rectMid(t spec) |
func rectMid(t spec) float64 { |
||
parts := make([] |
parts := make([]float64, t.n) |
||
r := t.upper - t.lower |
r := t.upper - t.lower |
||
nf := |
nf := float64(t.n) |
||
// there's a tiny gloss in the x1-x0 trick here. the correct way |
// there's a tiny gloss in the x1-x0 trick here. the correct way |
||
// would be to compute x's at division boundaries, but we don't need |
// would be to compute x's at division boundaries, but we don't need |
||
Line 1,089: | Line 1,087: | ||
x0 := t.lower - .5*r/nf |
x0 := t.lower - .5*r/nf |
||
for i := range parts { |
for i := range parts { |
||
x1 := t.lower + ( |
x1 := t.lower + (float64(i)+.5)*r/nf |
||
parts[i] = t.f(x1) * (x1 - x0) |
parts[i] = t.f(x1) * (x1 - x0) |
||
x0 = x1 |
x0 = x1 |
||
Line 1,096: | Line 1,094: | ||
} |
} |
||
func trap(t spec) |
func trap(t spec) float64 { |
||
parts := make([] |
parts := make([]float64, t.n) |
||
r := t.upper - t.lower |
r := t.upper - t.lower |
||
nf := |
nf := float64(t.n) |
||
x0 := t.lower |
x0 := t.lower |
||
f0 := t.f(x0) |
f0 := t.f(x0) |
||
for i := range parts { |
for i := range parts { |
||
x1 := t.lower + |
x1 := t.lower + float64(i+1)*r/nf |
||
f1 := t.f(x1) |
f1 := t.f(x1) |
||
parts[i] = (f0 + f1) * .5 * (x1 - x0) |
parts[i] = (f0 + f1) * .5 * (x1 - x0) |
||
Line 1,111: | Line 1,109: | ||
} |
} |
||
func simpson(t spec) |
func simpson(t spec) float64 { |
||
parts := make([] |
parts := make([]float64, 2*t.n+1) |
||
r := t.upper - t.lower |
r := t.upper - t.lower |
||
nf := |
nf := float64(t.n) |
||
// similar to the rectangle midpoint logic explained above, |
// similar to the rectangle midpoint logic explained above, |
||
// we play a little loose with the values used for dx and dx0. |
// we play a little loose with the values used for dx and dx0. |
||
Line 1,122: | Line 1,120: | ||
x0 := t.lower + dx0 |
x0 := t.lower + dx0 |
||
for i := 1; i < t.n; i++ { |
for i := 1; i < t.n; i++ { |
||
x1 := t.lower + |
x1 := t.lower + float64(i+1)*r/nf |
||
xmid := (x0 + x1) * .5 |
xmid := (x0 + x1) * .5 |
||
dx := x1 - x0 |
dx := x1 - x0 |
||
Line 1,131: | Line 1,129: | ||
parts[2*t.n] = t.f(t.upper) * dx0 |
parts[2*t.n] = t.f(t.upper) * dx0 |
||
return sum(parts) / 6 |
return sum(parts) / 6 |
||
} |
} |
||
// sum a list of numbers avoiding loss of precision |
// sum a list of numbers avoiding loss of precision |
||
// (there might be better ways...) |
|||
func sum(parts [] |
func sum(parts []float64) float64 { |
||
sort.SortFloats(parts) |
|||
sort.SortFloat64s(parts) |
|||
ip := sort.SearchFloat64s(parts, 0) |
|||
in := ip - 1 |
|||
sum := parts[ip] |
sum := parts[ip] |
||
ip++ |
ip++ |
||
Line 1,187: | Line 1,186: | ||
fmt.Println("") |
fmt.Println("") |
||
} |
} |
||
⚫ | |||
} |
|||
</lang> |
|||
Output: |
Output: |
||
⚫ | |||
<pre> |
|||
⚫ | |||
Integration from 0 to 1 in 100 parts |
Integration from 0 to 1 in 100 parts |
||
Exact result 2.5000000e-01 Error |
Exact result 2.5000000e-01 Error |
||
Rectangular (left) 2. |
Rectangular (left) 2.4502500e-01 4.9750000e-03 |
||
Rectangular (right) 2.5502500e-01 5. |
Rectangular (right) 2.5502500e-01 5.0250000e-03 |
||
Rectangular (midpoint) 2. |
Rectangular (midpoint) 2.4998750e-01 1.2500000e-05 |
||
Trapezium 2.5002500e-01 2. |
Trapezium 2.5002500e-01 2.5000000e-05 |
||
Simpson's 2. |
Simpson's 2.5000000e-01 5.5511151e-17 |
||
Test case: f(x) = 1/x |
Test case: f(x) = 1/x |
||
Integration from 1 to 100 in 1000 parts |
Integration from 1 to 100 in 1000 parts |
||
Exact result 4.6051702e+00 Error |
Exact result 4.6051702e+00 Error |
||
Rectangular (left) 4.6549911e+00 4.9820872e-02 |
|||
Rectangular (right) 4. |
Rectangular (right) 4.5569811e+00 4.8189128e-02 |
||
Rectangular (midpoint) 4. |
Rectangular (midpoint) 4.6047625e+00 4.0763731e-04 |
||
Trapezium 4.6059861e+00 8. |
Trapezium 4.6059861e+00 8.1587153e-04 |
||
Simpson's 4. |
Simpson's 4.6051704e+00 1.9896905e-07 |
||
Test case: f(x) = x |
Test case: f(x) = x |
||
Integration from 0 to 5000 in 500000 parts |
Integration from 0 to 5000 in 500000 parts |
||
Exact result 1.2500000e+07 Error |
Exact result 1.2500000e+07 Error |
||
Rectangular (left) 1. |
Rectangular (left) 1.2499975e+07 2.5000000e+01 |
||
Rectangular (right) 1. |
Rectangular (right) 1.2500025e+07 2.5000000e+01 |
||
Rectangular (midpoint) 1. |
Rectangular (midpoint) 1.2500000e+07 1.6763806e-08 |
||
Trapezium 1. |
Trapezium 1.2500000e+07 3.7252903e-08 |
||
Simpson's 1. |
Simpson's 1.2500000e+07 2.9802322e-08 |
||
Test case: f(x) = x |
Test case: f(x) = x |
||
Integration from 0 to 6000 in 6000000 parts |
Integration from 0 to 6000 in 6000000 parts |
||
Exact result 1.8000000e+07 Error |
Exact result 1.8000000e+07 Error |
||
Rectangular (left) 1. |
Rectangular (left) 1.7999997e+07 3.0000000e+00 |
||
Rectangular (right) 1. |
Rectangular (right) 1.8000003e+07 3.0000000e+00 |
||
Rectangular (midpoint) 1. |
Rectangular (midpoint) 1.8000000e+07 1.4901161e-08 |
||
Trapezium 1. |
Trapezium 1.8000000e+07 1.8626451e-08 |
||
Simpson's 1. |
Simpson's 1.8000000e+07 7.4505806e-09</pre> |
||
</pre> |
|||
=={{header|Haskell}}== |
=={{header|Haskell}}== |