Integrais definidas aproximadas usando somas de Riemann

19

As somas de Riemann esquerda e direita são aproximações para integrais definidas . Obviamente, em matemática, precisamos ser muito precisos; portanto, pretendemos calculá-las com várias subdivisões que se aproximam do infinito, mas isso não é necessário para os propósitos deste desafio. Em vez disso, você deve tentar escrever o programa mais curto, obtendo entrada e fornecendo saída através de qualquer um dos métodos padrão , em qualquer linguagem de programação , que faz o seguinte:

Tarefa

Dados dois números racionais a e b (os limites da integral definido), um número inteiro positivo n , um booleano k representando esquerda / para a direita e uma função de caixa preta f , calcular a soma de Riemann esquerda ou para a direita (dependendo k ) de abf(x)dx , usando n subdivisões iguais .

Especificações de E / S

  • a eb podem ser números / de ponto flutuante racional ou fracções.

  • k pode ser representado por dois valores distintos e consistentes, mas lembre-se de quevocê não tem permissãopara assumir funções completas ou parciais como entrada.

  • f é uma função de caixa preta. Citando a resposta da meta acima,o conteúdo (ou seja, o código) das funções da caixa preta pode não ser acessado, você pode chamá-las apenas (passar argumentos, se aplicável) e observar sua saída. Se necessário, inclua as informações necessárias sobre a sintaxe usada pelo seu idioma para que possamos testar seu envio.

Como saída, você deve fornecer uma fração / ponto flutuante / racional que representa a soma de Riemann solicitada. Como discutido no passado , a imprecisão de ponto flutuante pode ser ignorada, desde que sua saída seja precisa com pelo menos três casas decimais quando arredondada para o múltiplo mais próximo de 1/1000 (por exemplo, 1.4529999é bom em vez de 1.453).

Especificações matemáticas

  • f é a garantia de ser contínua entrea eb (sem saltos, sem furos, não há asymptotes verticais).

  • Há três casos possíveis com os quais você deve lidar: a=b (O resultado deve ser 0 ou equivalente), a<b ou a>b .

  • Se b<a , a integral altera seu sinal. Além disso, o sentido correto da integral, neste caso, é no sentido de a .

  • As áreas abaixo do gráfico são negativas e as acima do gráfico são positivas.

Exemplos / Casos de Teste

A resolução não é ótima, porque eu tive que reduzi-los um pouco, mas eles ainda são legíveis.

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

    2x + 1

    O resultado deve ser 152+192+232+272=168 , porque a largura de cada retângulo é |ba|n=2e as alturas correspondentes sãof(7)=15,f(9)=19,f(11)=23,f(13)=27 .

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

    Raiz quadrada

    A saída deve ser 1.8194792169 .

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

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

    (4.055.456.457.057.257.056.455.454.052.25)=55.5b<a

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

    9-4x + 2 / 7x ^ 2

    13.5714285715

  • f(x)=6,a=1,b=4,n=218

  • f(x)=x7+165x+1,a=7,b=7,n=40

  • f(x)=xsin(x1),a=0,b=1,n=500.385723952885505

Mr. Xcoder
fonte
3
Agradecimentos especiais: Esse desafio foi publicado na Sandbox , onde recebeu feedback valioso do usuário202729 , AdmBorkBork e Leaky Nun .
Xcoder
Espero que as soluções aqui ajudar a pena de estudantes Calc I muitos anos ...
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.Agora que f (x) é uma caixa preta, por que isso importa?
L4m2
@ l4m2 Não importa muito, só queria que as pessoas soubessem que não deveriam se preocupar com essas coisas.
Sr. Xcoder
@ Giuseppe Não. Os métodos dos programas aqui são ainda piores que os métodos das calculadoras portáteis. [apenas dizendo]
user202729

Respostas:

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

Experimente online!

Aceita k=FALSEsomas à direita, embora o link TIO agora inclua aliases para "esquerda" e "direita" para facilitar o uso.

a+w*(1:n-k) gera pontos adequados à esquerda ou à direita.

Em seguida, sapplyaplica f- se a cada elemento do resultado, que sumaumentamos e multiplicamos pela largura do intervalo (b-a)/npara produzir o resultado. Este último também cuida de qualquer problema de sinal que possamos ter.

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

Experimente online!

Supondo que a função pesteja definida em algum lugar, isso leva a,b,n,k,(name of p), com k=0para a direita e l=1para a esquerda.

O catspaw's SNOBOL4+suporta REALs, mas não possui funções trigonométricas embutidas. No entanto, suponho que alguém possa ter uma sinfunção razoável usando uma série de taylor.

Não tenho 100% de certeza de que essa é a maneira "correta" de passar uma função de caixa preta no SNOBOL (que, a meu conhecimento, não possui funções de primeira classe), mas me parece razoável.

Suponho que assumindo que a função seja definida como fmenor, pois a linha lpode ser

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

mas não é passado como argumento, que parece um pouco como "trapaça".

Observe que o link TIO possui uma instrução :(e)after DEFINE, que é para que o código realmente seja executado corretamente.

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

Experimente online!

Um intervalo normalizado é construído, coletado em um vetor e depois escalado. A coleta do intervalo em um vetor usando [X...]é necessária para evitar a inexact errormultiplicação do intervalo diretamente por 0 quando a=b. Da mesma forma, construir um intervalo diretamente com :ou range()não é possível quando a=b.

O uso de k é muito semelhante à solução de Guiseppe , com k=1for righte k=0for left.

LukeS
fonte
f.vetoriza fseus argumentos?
Giuseppe
@ Giuseppe: Exatamente. f.é a aplicação elemento a elemento de f.
LukeS
2

Haskell , 73 67 bytes

Obrigado a H.PWiz e Bruce Forte pelas dicas!

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

Experimente online!

Solução bastante simples.

ké 0para a esquerda e 1para a direita.

Cristian Lupascu
fonte
11
Se você está tomando n, você não precisa ir atéb
H.PWiz
2

Python 2 , 99 94 bytes

Um pouco de uma solução ingênua.

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

Experimente online!

mbomb007
fonte
94 bytes em Python 2
Mr. Xcoder 25/07
Por alguma razão, pensei que tínhamos que lidar com entradas inteiras. Obrigado.
mbomb007 25/07
1

Geléia , 21 bytes

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

Experimente online!

Retire a,bdos argumentos e

n
right
f

de stdin.


Se você não conhece o Jelly, pode usar o Python para escrever a função de caixa preta f:

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

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

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

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

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

f (x) = x * sen (1 / x) ; a = 0; b = 1; n = 50; k = direita


Explicação:


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

Perl 6 , 65 bytes

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

Experimente online!

Relativamente simples. A única complicação está a tratar do a > bcaso, o que eu faço por xor-ing a bandeira de entrada $^kcom 0 > d, o que inverte quando a > b.

Sean
fonte
0

APL (Dyalog Classic) , 37 bytes

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

Experimente online!

APL NARS, 37 caracteres

A função tem o argumento à esquerda da função, no argumento numérico à direita abn k. Na questão k = deixada aqui, significa k = ¯1; k = aqui significa k = 0. Teste:

  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
fonte
Os envios são contados em bytes, não em caracteres. Não me lembro se o NARS tem uma página de código personalizada (portanto, seria também 37 bytes) ou usa UTF16.
Uriel
@ Uriel São 37 bytes no Dyalog APL classic, siga o link; possivelmente 35x2 bytes para o Nars Apl ...
RosLuP
Então, por que você escreve como NARS? O NARS ainda tem dfnss? Pela maneira que você pode deixar cair os primeiros pais por 35 bytes
Uriel
APL NARS, 37 caracteres significa que ele deve ser executado em NARS APL também
RosLuP