Integrali definiti approssimativi usando le somme di Riemann


19

Le somme di Riemann sinistro e destro sono approssimazioni di integrali definiti . Certo, in matematica dobbiamo essere molto precisi, quindi miriamo a calcolarli con una serie di suddivisioni che si avvicinano all'infinito, ma non è necessario ai fini di questa sfida. Dovresti invece provare a scrivere il programma più breve, prendendo input e fornendo output attraverso uno dei metodi predefiniti , in qualsiasi linguaggio di programmazione , che procede come segue:

Compito

Dati due numeri razionali e (i limiti della integrale definito), un numero intero positivo , un valore booleano in rappresentanza della sinistra / destra e di una funzione di black-box , calcolare la somma di Riemann a sinistra oa destra (a seconda ) di , usando suddivisioni uguali .un'BnK fKun'Bf(X)dXn

Specifiche I / O

  • un' e possono essere numeri in virgola mobile razionale / o frazioni. B

  • K può essere rappresentato da due valori distinti e coerenti, ma tieni presente che non puoi assumere funzioni complete o parziali come input.

  • f è una funzione di casella nera. Citando la meta risposta collegata sopra, il contenuto (cioè il codice) delle funzioni della scatola nera non è accessibile, puoi solo chiamarli (passando argomenti se applicabile) e osservarne l'output . Se necessario, si prega di includere le informazioni necessarie sulla sintassi utilizzata dalla propria lingua in modo tale da poter testare l'invio.

Come output, è necessario fornire una razionale / virgola mobile / frazione che rappresenta la somma di Riemann richiesta. Come discusso in passato , l'imprecisione in virgola mobile può essere ignorata, purché l'output sia accurato con almeno tre cifre decimali quando arrotondato al multiplo più vicino di 1/1000 (ad esempio 1.4529999va bene invece che 1.453).

Specifiche matematiche

  • f è garantito per essere continuo tra e (senza salti, buchi, nessun asintoti verticali).un'B

  • Esistono tre casi possibili che devi gestire: (il risultato dovrebbe essere o suoi equivalenti), a <b o a> b .un'=B0un'<Bun'>B

  • Se B<un' , l'integrale cambia segno. Inoltre, il giusto senso dell'integrale in questo caso è verso un' .

  • Le aree sotto il grafico sono negative e quelle sopra il grafico sono positive.

Esempi / casi di test

La risoluzione non è ottimale, perché ho dovuto ridurli un po ', ma sono ancora leggibili.

  • f(X)=2X+1,un'=5,B=13,n=4 , k = destra:

    2x + 1

    Il risultato dovrebbe essere , perché la larghezza di ciascun rettangolo è e il corrispondente le altezze sono .152+192+232+272=168|ba|n=2f(7)=15,f(9)=19,f(11)=23,f(13)=27

  • f(x)=x,a=1,b=2.5,n=3 , k = left:

    Radice quadrata

    L'output dovrebbe essere .1.8194792169

  • f(x)=-3X+4+X25,un'=12.5,B=2.5,n=10 , k = right:

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

    Il valore di output atteso è , poiché l'integrale cambia segno quando si invertono i confini ( ) .-(-4.05-5.45-6.45-7.05-7.25-7.05-6.45-5.45-4.05-2.25)=55.5b < aB<un'

  • f(X)=9-4X+2X27,un'=0,B=15,n=3 , k = left:

    9-4x + 2 / 7x 2 ^

    Calcolando la nostra somma di Riemann, otteniamo .13,5714,285715 millions

  • f(X)=6,un'=1,B=4,n=2 , k = right - Uscita: .18

  • f(X)=X7+165X+1,un'=7,B=7,n=4 , k = left - Uscita: .0

  • f(X)=Xpeccato(X-1),un'=0,B=1,n=50 , k = right - Output: . Nota che qui sinusoide usa i radianti, ma sentiti libero di usare i gradi.,385723952885505


3
Un ringraziamento speciale: questa sfida è stata pubblicata nella Sandbox , dove ha ricevuto feedback preziosi da user202729 , AdmBorkBork e Leaky Nun .
Mr. Xcoder,

Spero davvero che le soluzioni qui aiutino gli studenti di Calc I per molti anni ...
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.Ora che f (x) è una scatola nera perché è importante?
l4m2

@ l4m2 Non importa molto, volevo solo far sapere alle persone che non dovrebbero preoccuparsi di queste cose.
Mr. Xcoder il

@Giuseppe No. I metodi dei programmi qui sono persino peggiori dei metodi dei calcolatori portatili. [solo dicendo]
user202729

Risposte:


8

R , 69 65 63 57 byte

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

Provalo online!

Prende k=FALSEper le somme a destra, sebbene il collegamento TIO ora includa alias per "sinistra" e "destra" per facilità d'uso.

a+w*(1:n-k) genera punti appropriati per la mano sinistra o destra.

Quindi si sapplyapplica fa ciascun elemento del risultato, che quindi sumaumentiamo e moltiplichiamo per la larghezza dell'intervallo (b-a)/nper produrre il risultato. Quest'ultimo si occupa anche ordinatamente di eventuali problemi di segno che potremmo avere.


4

SNOBOL4 (CSNOBOL4) , 127 byte

	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)

Provalo online!

Supponendo che la funzione psia definita da qualche parte, ciò richiede a,b,n,k,(name of p), con k=0per destra e l=1per sinistra.

catspaw's SNOBOL4+supporta REALs ma non ha funzioni di trigger integrate. Tuttavia, suppongo che si potrebbe trovare una sinfunzione ragionevole usando una serie di Taylor.

Non sono sicuro al 100% che questo sia il modo "giusto" per passare una funzione black-box in SNOBOL (che, per quanto ne so, non ha funzioni di prima classe), ma mi sembra ragionevole.

Suppongo che assumere la funzione sia definita come fsarebbe più breve, come lpotrebbe essere la linea

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

ma poi non è passato come argomento, che sembra un po '"barare".

Si noti che il collegamento TIO ha un'istruzione :(e)after DEFINE, che consente al codice di funzionare correttamente.


4

Julia 0.6 , 50 byte

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

Provalo online!

Viene costruito un intervallo normalizzato, raccolto in un vettore e quindi ridimensionato. La raccolta dell'intervallo in un vettore mediante [X...]è necessaria per evitare il inexact errormoltiplicare l'intervallo direttamente con 0 quando a=b. Allo stesso modo, costruire un intervallo direttamente con :o range()non è possibile quando a=b.

L'uso di k è molto simile alla soluzione di Guiseppe , con k=1for righte k=0for left.


f.vettorializza i fsuoi argomenti?
Giuseppe,

@Giuseppe: Esatto. f.è l'applicazione saggia di f.
LukeS

2

Haskell , 73 67 byte

Grazie a H.PWiz e Bruce Forte per i suggerimenti!

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

Provalo online!

Soluzione piuttosto semplice.

kè 0per sinistra e 1per destra.


1
Se stai prendendo n, non devi andare fino ab
H.Pwiz



1

Gelatina , 21 byte

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

Provalo online!

Prendi a,bdagli argomenti, e

n
right
f

da stdin.


Se non hai familiarità con Jelly, puoi usare Python per scrivere la funzione scatola nera f:

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

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

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

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

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

f (x) = x * sin (1 / x) ; a = 0; b = 1; n = 50; k = destra


Spiegazione:


ƓḶ+Ɠ÷     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`.


1

Perl 6 , 65 byte

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

Provalo online!

Relativamente semplice. L'unica complicazione è gestire il a > bcaso, cosa che faccio xorando il flag di input $^kcon 0 > d, che lo inverte quando a > b.


0

APL (Dyalog Classic) , 37 byte

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

Provalo online!

APL NARS, 37 caratteri

La funzione ha l'argomento a sinistra della funzione, nell'argomento numerico a destra abn k. Nella domanda k = lasciato qui significa k = ¯1; k = proprio qui significa k = 0. Test:

  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

Gli invii sono conteggiati in byte, non in caratteri. Non ricordo se NARS ha una tabella codici personalizzata (quindi sarebbe anche 37 byte) o usa UTF16.
Uriel,

@Uriel Sono 37 byte in Dyalog APL classico segui il link; forse 35x2 byte per Nars Apl ...
RosLuP il

Quindi perché lo scrivi come NARS? NARS ha anche dfnss? A proposito, puoi eliminare i primi genitori per 35 byte
Uriel il

APL NARS, 37 caratteri significa che dovrebbe funzionare anche in NARS APL
RosLuP
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.