Intégrales définitives approximatives utilisant les sommes de Riemann

19

Les sommes de Riemann gauche et droite sont des approximations d' intégrales définies . Bien sûr, en mathématiques, nous devons être très précis, nous visons donc à les calculer avec un certain nombre de subdivisions qui approchent de l'infini, mais ce n'est pas nécessaire aux fins de ce défi. Vous devriez plutôt essayer d'écrire le programme le plus court, en prenant l'entrée et en fournissant la sortie par l'une des méthodes par défaut , dans n'importe quel langage de programmation , ce qui fait ce qui suit:

Tâche

Étant donné deux nombres rationnels a et b (les limites de l'intégrale définie), un entier positif n , un booléen k représentant gauche / droite et une fonction boîte noire f , calculez la somme de Riemann gauche ou droite (en fonction de k ) de abf(x)dx , en utilisant n subdivisions égales .

Spécifications d'E / S

  • a etb peuvent être des nombres ou des fractions rationnelles / à virgule flottante.

  • k peut être représenté par deux valeurs distinctes et cohérentes, mais gardez à l'esprit quevous n'êtes pas autoriséà prendre des fonctions complètes ou partielles en entrée.

  • f est une fonction de boîte noire. En citant la méta-réponse liée ci-dessus,le contenu (c'est-à-dire le code) des fonctions de boîte noire n'est pas accessible, vous pouvez seulement les appeler (en passant des arguments le cas échéant) et observer leur sortie. Si nécessaire, veuillez inclure les informations nécessaires sur la syntaxe utilisée par votre langue afin que nous puissions tester votre soumission.

En sortie, vous devez fournir une fraction rationnelle / virgule flottante / représentant la somme de Riemann qui vous est demandée. Comme discuté dans le passé , l'imprécision en virgule flottante peut être ignorée, tant que votre sortie est précise à au moins trois décimales lorsqu'elle est arrondie au multiple le plus proche de 1/1000 (par exemple, 1.4529999c'est bien au lieu de 1.453).

Spécifications mathématiques

  • f est garanti d'être continu entrea etb (pas de sauts, pas de trous, pas d'asymptotes verticales).

  • Vous devez gérer trois cas: (le résultat doit être ou ses équivalents), ou .a=b0a<ba>b

  • Si , l'intégrale change de signe. En outre, le bon sens de l'intégrale dans ce cas est vers .b<aa

  • Les zones sous le graphique sont négatives et celles au-dessus du graphique sont positives.

Exemples / cas de test

La résolution n'est pas optimale, car j'ai dû les réduire un peu, mais elles sont toujours lisibles.

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

    2x + 1

    Le résultat doit être 152+192+232+272=168 , car la largeur de chaque rectangle est |ba|n=2et les hauteurs correspondantes sontf(7)=15,f(9)=19,f(11)=23,f(13)=27 .

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

    Racine carrée

    La sortie doit être 1.8194792169 .

  • f(x)=3x+4+x25,a=12.5,b=2.5,n=10 , k = droite:

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

    La valeur de sortie attendue est (4.055.456.457.057.257.056.455.454.052.25)=55.5 , car l'intégrale change de signe lors du retournement des limites ( b<a ) .

  • f(x)=94x+2x27,a=0,b=15,n=3 , k = gauche:

    9-4x + 2 / 7x ^ 2

    En calculant notre somme de Riemann, nous obtenons 13.5714285715 .

  • f(x)=6,a=1,b=4,n=2 , k = droite - Sortie:18 .

  • f(x)=x7+165x+1,a=7,b=7,n=4 , k = gauche - Sortie:0 .

  • f(x)=xsin(x1),a=0,b=1,n=50 , k = droite - Sortie:0.385723952885505 . Notez que le sinus utilise des radians ici, mais n'hésitez pas à utiliser des degrés à la place.

M. Xcoder
la source
3
Remerciements spéciaux: Ce défi a été publié dans le bac à sable , où il a reçu de précieux commentaires de la part de user202729 , AdmBorkBork et Leaky Nun .
M. Xcoder
J'espère bien que les solutions ici aideront les élèves de Calc I pendant de nombreuses années ...
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.Maintenant que f (x) est une boîte noire, pourquoi est-ce important?
l4m2
@ l4m2 Peu importe, je voulais juste faire savoir aux gens qu'ils ne devraient pas s'inquiéter de telles choses.
M. Xcoder
@Giuseppe Non. Les méthodes des programmes ici sont encore pires que les méthodes des calculatrices portables. [
Je

Réponses:

8

R , 69 65 63 57 octets

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

Essayez-le en ligne!

Prend k=FALSEpour les sommes de droite, bien que le lien TIO comprenne maintenant des alias pour "gauche" et "droite" pour une facilité d'utilisation.

a+w*(1:n-k) génère des points appropriés à gauche ou à droite.

sapplyS'applique ensuite fà chaque élément du résultat, que nous sumaugmentons ensuite et multiplions par la largeur (b-a)/nde l'intervalle pour donner le résultat. Ce dernier prend également parfaitement en charge tous les problèmes de signalisation que nous pourrions avoir.

Giuseppe
la source
4

SNOBOL4 (CSNOBOL4) , 127 octets

	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)

Essayez-le en ligne!

En supposant que la fonction pest définie quelque part, cela prend a,b,n,k,(name of p), avec k=0pour droite et l=1pour gauche.

catspaw SNOBOL4+prend en charge REALs mais n'a pas de fonctions trig intégrées. Cependant, je suppose que l'on pourrait trouver une sinfonction raisonnable en utilisant une série taylor.

Je ne suis pas sûr à 100% que c'est la "bonne" façon de passer une fonction de boîte noire dans SNOBOL (qui, à ma connaissance, n'a pas de fonctions de première classe), mais cela me semble raisonnable.

Je suppose que si la fonction est définie comme fétant plus courte, la ligne lpourrait être

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

mais alors ce n'est pas passé comme argument, ce qui ressemble un peu à de la "tricherie".

Notez que le lien TIO a un :(e)après l' DEFINEinstruction, ce qui permet au code de s'exécuter correctement.

Giuseppe
la source
4

Julia 0,6 , 50 octets

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

Essayez-le en ligne!

Une plage normalisée est construite, collectée dans un vecteur puis mise à l'échelle. La collecte de la plage dans un vecteur à l'aide [X...]est nécessaire pour éviter le inexact errorlors de la multiplication directe de la plage par 0 lorsque a=b. De même, construire une plage directement avec :ou range()n'est pas possible quand a=b.

L'utilisation de k est très similaire à la solution de Guiseppe , avec k=1pour rightet k=0pour left.

LukeS
la source
f.vectorise fsur ses arguments?
Giuseppe
@Giuseppe: Exactement. f.est une application élémentaire de f.
LukeS
2

Haskell , 73 67 octets

Merci à H.PWiz et Bruce Forte pour les conseils!

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

Essayez-le en ligne!

Solution assez simple.

kest 0pour la gauche et 1pour la droite.

Cristian Lupascu
la source
1
Si vous prenez n, vous n'avez pas besoin de monter jusqu'àb
H.PWiz
2

Python 2 , 99 94 octets

Un peu d'une solution naïve.

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))

Essayez-le en ligne!

mbomb007
la source
Pour une raison quelconque, je pensais que nous devions gérer les entrées entières. Merci.
mbomb007
1

Gelée , 21 octets

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

Essayez-le en ligne!

Prendre a,bdes arguments, et

n
right
f

de stdin.


Si vous n'êtes pas familier avec Jelly, vous pouvez utiliser Python pour écrire la fonction de boîte noire f:

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

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

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

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

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

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


Explication:


ƓḶ+Ɠ÷     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
la source
1

Perl 6 , 65 octets

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

Essayez-le en ligne!

Relativement simple. La seule complication est de gérer le a > bcas, ce que je fais en xorant le drapeau d'entrée $^kavec 0 > d, ce qui l'inverse quand a > b.

Sean
la source
0

APL (Dyalog Classic) , 37 octets

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

Essayez-le en ligne!

APL NARS, 37 caractères

La fonction a l'argument dans la fonction gauche, dans l'argument numérique droit abn k. Dans la question k = laissé ici, cela signifie k = ¯1; k = ici, cela signifie k = 0. Tester:

  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
la source
Les soumissions sont comptées en octets, pas en caractères. Je ne me souviens pas si NARS a une page de codes personnalisée (donc ce serait aussi 37 octets) ou utilise UTF16.
Uriel
@Uriel Il fait 37 octets dans Dyalog APL classic suivez le lien; éventuellement 35x2 octets pour Nars Apl ...
RosLuP
Alors pourquoi l'écrivez-vous en tant que NARS? NARS a-t-il même dfnss? Soit dit en passant, vous pouvez supprimer les premiers parents pour 35 octets
Uriel
APL NARS, 37 caractères signifie qu'il devrait également fonctionner dans NARS APL
RosLuP