Näherungsweise bestimmte Integrale unter Verwendung von Riemannschen Summen

19

Linke und rechte Riemann-Summen sind Annäherungen an bestimmte Integrale . Natürlich müssen wir in der Mathematik sehr genau sein, deshalb versuchen wir, sie mit einer Reihe von Unterteilungen zu berechnen, die gegen unendlich gehen, aber das wird für die Zwecke dieser Herausforderung nicht benötigt. Sie sollten stattdessen versuchen, das kürzeste Programm zu schreiben, indem Sie Eingaben und Ausgaben mit einer der Standardmethoden in einer beliebigen Programmiersprache vornehmen , die Folgendes ausführen:

Aufgabe

Mit zwei rationalen Zahlen und (den Grenzen des bestimmten Integrals), einer positiven ganzen Zahl , einem Booleschen für left / right und einer Black-Box-Funktion berechnen Sie die linke oder rechte Riemann-Summe (in Abhängigkeit von k ) von \ int_a ^ bf (x) \ mathrm {d} x mit n gleichen Unterteilungen.abnk fkabf(x)dxn

E / A-Spezifikationen

  • ein undb können rationale / Gleitkommazahlen oder Brüche sein.

  • k kann durch zwei unterschiedliche und konsistente Werte dargestellt werden. Beachten Sie jedoch, dass Sie keine vollständigen oder teilweisen Funktionen als Eingabe verwenden dürfen.

  • f ist eine Black-Box-Funktion. Unter Berufung auf die oben verlinkte Meta-Antwort kann möglicherweise nicht auf den Inhalt (dh den Code) von Black-Box-Funktionen zugegriffen werden. Sie können sie nur aufrufen (ggf. Argumente übergeben) und ihre Ausgabe beobachten . Geben Sie bei Bedarf die erforderlichen Informationen zu der von Ihrer Sprache verwendeten Syntax an, damit wir Ihren Beitrag testen können.

Als Ausgabe müssen Sie einen rationalen Gleitkomma-Bruch angeben, der die Riemann-Summe darstellt, nach der Sie gefragt werden. Wie bereits erwähnt , kann die Gleitkomma-Ungenauigkeit ignoriert werden, solange Ihre Ausgabe auf mindestens drei Dezimalstellen genau ist, wenn sie auf das nächste Vielfache von 1/1000 gerundet wird (z. B. 1.4529999ist in Ordnung statt 1.453).

Math Specs

  • f ist garantiert durchgehend zwischen und (keine Sprünge, keine Löcher, keine vertikalen Asymptoten).einb

  • Es gibt drei mögliche Fälle, die Sie behandeln müssen: (Das Ergebnis sollte oder dessen Äquivalente sein), oder .ein=b0ein<bein>b

  • Wenn , ändert das Integral sein Vorzeichen. Auch der richtige Sinn des Integrals ist in diesem Fall in Richtung .b<einein

  • Bereiche unter dem Diagramm sind negativ und diejenigen über dem Diagramm sind positiv.

Beispiele / Testfälle

Die Auflösung ist nicht optimal, weil ich sie etwas verkleinern musste, aber sie sind immer noch lesbar.

  • f(x)=2x+1,ein=5,b=13,n=4 , k = rechts:

    2x + 1

    Das Ergebnis sollte , da die Breite jedes Rechtecks und die entsprechende ist Die Höhen sind .152+192+232+272=168|b-ein|n=2f(7)=15,f(9)=19,f(11)=23,f(13)=27

  • f(x)=x,ein=1,b=2.5,n=3 , k = links:

    Quadratwurzel

    Die Ausgabe sollte .1.8194792169

  • f(x)=-3x+4+x25,ein=12.5,b=2.5,n=10 , k = rechts:

    -3x + 4 + 1 / 5x ^ 2

    Der erwartete Ausgabewert ist , da das Integral beim Umkehren der Grenzen das Vorzeichen ändert ( ) .-(-4,05-5.45-6.45-7.05-7.25-7.05-6.45-5.45-4,05-2.25)=55,5b < ab<ein

  • f(x)=9-4x+2x27,ein=0,b=15,n=3 , k = left:

    9-4x + 2 / 7x ^ 2

    wir unsere Riemann-Summe berechnen, erhalten wir .13.5714285715

  • f(x)=6,ein=1,b=4,n=2 , k = rechts - Ausgabe: .18

  • f(x)=x7+165x+1,ein=7,b=7,n=4 , k = links - Ausgabe: .0

  • f(x)=xSünde(x-1),ein=0,b=1,n=50 , k = rechts - Ausgabe: . Beachten Sie, dass der Sinus hier Bogenmaß verwendet, Sie können jedoch auch Grad verwenden.0,385723952885505

Mr. Xcoder
quelle
3
Besonderer Dank: Diese Herausforderung wurde in der Sandbox veröffentlicht , wo sie wertvolles Feedback von User202729 , AdmBorkBork und Leaky Nun erhalten hat .
Mr. Xcoder
Ich hoffe sehr, dass die Lösungen hier den Calc I-Schülern viele Jahre lang weiterhelfen ...
Giuseppe
f(x) = x * sin(1 / x); a = 0; b = 1; n = 50; k = right — Output: 0.385723952885505. Note that sine uses radians here, but feel free to use degrees instead.Nun, da f (x) eine Blackbox ist, warum ist das wichtig?
14.
@ l4m2 Es macht nicht viel aus, wollte die Leute nur wissen lassen, dass sie sich über solche Dinge keine Sorgen machen sollten.
Mr. Xcoder
@ Giuseppe Nein. Die Methoden von Programmen sind hier noch schlechter als die von Taschenrechnern. [nur sagen]
user202729

Antworten:

8

R , 69 65 63 57 Bytes

function(a,b,n,k,f,w=(b-a)/n)sum(sapply(a+w*(1:n-k),f))*w

Probieren Sie es online!

Nimmt k=FALSEfür Rechtssummen, obwohl der TIO-Link jetzt Aliase für "links" und "rechts" für die Benutzerfreundlichkeit enthält.

a+w*(1:n-k) erzeugt entsprechende Punkte für die linke oder rechte Hand.

Dann sapplygilt ffür jedes Element des Ergebnisses, das wir dann sumaufaddieren und mit der Intervallbreite multiplizieren (b-a)/n, um das Ergebnis zu erhalten. Letzteres kümmert sich auch ordentlich um alle Schilderprobleme, die wir haben könnten.

Giuseppe
quelle
4

SNOBOL4 (CSNOBOL4) , 127 Bytes

	DEFINE('R(a,b,n,k,p)')
R	l =(b - a) / n
	i =1
l	R =R + eval(p '(a + l * (i - k))')
	i =lt(i,n) i + 1	:s(l)
	R =R * l :(return)

Probieren Sie es online!

Vorausgesetzt, die Funktion pist irgendwo definiert, dauert dies a,b,n,k,(name of p)mit k=0für rechts und l=1für links.

catspaw's SNOBOL4+unterstützt REALs, hat aber keine eingebauten Triggerfunktionen. Ich nehme jedoch an, dass man sinmit einer Taylor-Serie eine vernünftige Funktion finden könnte .

Ich bin mir nicht 100% sicher, ob dies der "richtige" Weg ist, eine Black-Box-Funktion in SNOBOL (die meines Wissens keine erstklassigen Funktionen hat) zu übergeben, aber es scheint mir vernünftig.

Ich nehme an, dass unter der Annahme, dass die Funktion als fkürzer definiert ist, als die Linie sein lkönnte

l	R =R + f(a + l * (i - k))

aber dann wird es nicht als Argument übergeben, was sich ein bisschen wie "Schummeln" anfühlt.

Beachten Sie, dass der TIO-Link :(e)nach der DEFINEAnweisung ein steht, sodass der Code tatsächlich ordnungsgemäß ausgeführt wird.

Giuseppe
quelle
4

Julia 0,6 , 50 Bytes

R(f,a,b,n,k)=(c=(b-a)/n;sum(f.(a+[k:n+k-1...]c))c)

Probieren Sie es online!

Ein normalisierter Bereich wird konstruiert, in einem Vektor gesammelt und dann skaliert. Das Erfassen des Bereichs in einem Vektor unter Verwendung von [X...]ist erforderlich, um zu vermeiden, dass inexact errorbeim Multiplizieren des Bereichs direkt mit 0 der Wert "when" verwendet wird a=b. Ebenso ist das direkte Erstellen eines Bereichs mit :oder range()nicht möglich, wenn a=b.

Die Verwendung von k ist der Lösung von Guiseppe mit k=1für rightund k=0für sehr ähnlich left.

LukeS
quelle
f.vektorisiert füber seine Argumente?
Giuseppe
@ Giuseppe: Genau. f.ist elementweise Anwendung von f.
LukeS
2

Haskell , 73 67 Bytes

Vielen Dank an H.PWiz und Bruce Forte für die Tipps!

(f&a)b n k|d<-(b-a)/realToFrac n=d*sum(f<$>take n(drop k[a,a+d..]))

Probieren Sie es online!

Ziemlich einfache Lösung.

kist 0für links und 1für rechts.

Cristian Lupascu
quelle
1
Wenn Sie n nehmen, müssen Sie nicht aufb
H.PWiz
2

Python 2 , 99 94 Bytes

Ein bisschen wie eine naive Lösung.

def R(f,a,b,n,k):s=cmp(b,a);d=s*(b-a)/n;return s*sum(d*f([0,a,b][s]+i*d)for i in range(k,n+k))

Probieren Sie es online!

mbomb007
quelle
Aus irgendeinem Grund dachte ich, wir müssten mit Integer-Eingaben umgehen. Vielen Dank.
mbomb007
1

Jelly , 21 Bytes

ƓḶ+Ɠ÷
IḢ×¢A+ṂɠvЀÆm×I

Probieren Sie es online!

Nehmen Sie a,baus Argumenten und

n
right
f

von stdin.


Wenn Sie mit Jelly nicht vertraut sind, können Sie mit Python die Blackbox-Funktion schreiben f:

f (x) = 2x + 1 ; a = 5; b = 13; n = 4; k = richtig

f (x) = √x ; a = 1; b = 2,5; n = 3; k = links

f (x) = -3x + 4 + 1/5 * x 2 ; a = 12,5; b = 2,5; n = 10; k = richtig

f (x) = 9 - 4x + 2/7 * x 2 ; a = 0; b = 15; n = 3; k = links

f (x) = 6 ; a = 1; b = 4; n = 2; k = richtig

f (x) = x · sin (1 / x) ; a = 0; b = 1; n = 50; k = richtig


Erläuterung:


ƓḶ+Ɠ÷     Helper niladic link.
Ɠ         First line from stdin. (n). Assume n = 4.
 Ḷ        Lowered range (unlength). Get [0, 1, 2, 3].
  +Ɠ      Add second line from stdin (k). Assume k = 1 (right).
            Get [1, 2, 3, 4].
    ÷     Divide by (n). Get [0.25,0.5,0.75,1].

IḢ×¢A+ṂɠvЀÆm×I   Main monadic link. Take input `[a, b]`, assume `a=2,b=6`.
IḢ                `a-b`. Get `-4`.
  ×¢              Multiply by value of niladic link above. Get `[-1,-2,-3,-4]`.
    A             Absolute value. Get `[1,2,3,4]`.
     +Ṃ           Add min(a, b) = 2. Get `[3,4,5,6]`.
        vЀ       For each number, evaluate with...
       ɠ            input line from stdin.
           Æm     Arithmetic mean.
             ×I   Multiply by `a-b`.

user202729
quelle
1

Perl 6 , 65 Bytes

{my \d=($^b-$^a)/$^n;sum ($a,*+d...*)[($^k+^0>d)+ ^$n]».&^f X*d}

Probieren Sie es online!

Relativ einfach. Die einzige Komplikation ist der Umgang mit dem a > bFall, die ich von xor-ing tun , um den Eingang Flagge $^kmit 0 > d, es welcher umkehrt , wenn a > b.

Sean
quelle
0

APL (Dyalog Classic) , 37 Byte

{(a b n k)←⍵⋄ln÷⍨b-al×+/⍺⍺a+l×k+⍳n}

Probieren Sie es online!

APL NARS, 37 Zeichen

Die Funktion hat links das Argument, rechts das numerische Argument abn k. In der Frage k = hier links bedeutet es k = ¯ 1; k = genau hier bedeutet es k = 0. Prüfung:

  f←{(a b n k)←⍵⋄ln÷⍨b-al×+/⍺⍺a+l×k+⍳n}
  {1+2×⍵} f 5 13 4 0
168
  {√⍵} f 1 2.5 3 ¯1
1.819479217
  {4+(¯3×⍵)+0.2×⍵×⍵} f 12.5 2.5 10 0
55.5
  {9+(¯4×⍵)+7÷⍨2×⍵×⍵} f 0 15 3 ¯1
13.57142857
  {6-0×⍵} f 1 4 2 0
18
  {1+(165×⍵)+⍵*7} f 7 7 4 ¯1
0
  {⍵×1○÷⍵} f 0 1 50 0
0.3857239529
RosLuP
quelle
Einsendungen werden in Bytes und nicht in Zeichen gezählt. Ich erinnere mich nicht, ob NARS eine benutzerdefinierte Codepage hat (also auch 37 Byte) oder UTF16 verwendet.
Uriel
@Uriel Es sind 37 Bytes in Dyalog APL classic. Folgen Sie dem Link. Möglicherweise 35x2 Bytes für Nars Apl ...
RosLuP
Warum schreibst du es dann als NARS? Hat NARS überhaupt dfnss? Übrigens können Sie die ersten Eltern für 35 Bytes fallen lassen
Uriel
APL NARS, 37 Zeichen bedeutet, dass es auch in NARS APL ausgeführt werden sollte
RosLuP