P i = = 3. 2

37

Inspirado por este vídeo da série Infinite .

Introdução

Pi é definido como a razão da circunferência para o diâmetro de um círculo. Mas como um círculo é definido? Normalmente, um círculo é definido como os pontos com distância constante ao ponto central (suponhamos que o centro esteja (0,0)). A próxima pergunta seria: como definimos a distância ? A seguir, estamos considerando diferentes noções de distâncias (induzidas pelas Lp-norms):

Dada uma norma (= algo que mede um comprimento ), podemos facilmente construir uma distância (= distância entre dois pontos) da seguinte maneira:

dist(A,B) := norm (A-B)

A norma euclidiana é dada por:

norm((x,y)) = (x^2 + y^2)^(1/2)

Isso também é chamado de norma L2 . As outras normas Lp são construídas substituindo 2na fórmula acima por outros valores entre 1 e infinito:

norm_p((x,y)) = (|x|^p + |y|^p)^(1/p)

Os círculos unitários para essas diferentes normas têm formas bastante distintas:

Desafio

Dado a p >= 1, calcule a razão da circunferência para o diâmetro de um círculo Lp em relação à Lp-norm com uma precisão de quatro algarismos significativos.

Casos de teste

Podemos usar isso para p,qcom 1 = 1/p + 1/qnós começamos a mesma relação para o Lpbem como a Lqnorma. Além disso, para p = q = 2a relação é mínima, e para p = 1, q = infinityobtermos uma relação de 4, as relações estão sempre entre pie 4.

p   or  q            ratio
1       infinity     4
2       2            3.141592
1.623   2.60513      3.200
1.5     3            3.25976
4       1.33333      3.39693
flawr
fonte
2
As formas são conhecidas como curvas de Lamé ou superellipses e existem para 0 < p <1 também, mesmo que a norma em si não exista (porque viola a desigualdade do triângulo). O artigo da Wikipedia para a superellipse inclui um formulário fechado para a área.
Neil
@ Neil No entanto, precisamos considerar a circunferência, não a área, que - até onde eu sei - só pode ser calculada através de uma integral de comprimento de arco.
flawr
7
Desculpe, quando terminei de ler sobre eles e tinha esquecido o que a pergunta pedia.
Neil
2
Adorável desafio!
Luis Mendo
1
É interessante notar que a fórmula da área ( A = πr²) não é válida parap ≠ 2
Mego

Respostas:

12

Python + scipy, 92 bytes

from scipy.integrate import*
lambda p:2/p*quad(lambda x:(x/x**p+(1-x)**(1-p))**(1/p),0,1)[0]

Fórmula é a partir desta questão math.SE .

orlp
fonte
Ao testar uma implementação com esta abordagem, tive problemas com a convergência dessa abordagem, devido à singularidade em x=1, como é que a sua submissão é realizada?
flawr
O Scipy não faz parte da biblioteca padrão do Python. Talvez mude para Sage?
precisa saber é
2
@busukxuan Não há requisito no PPCG que permita que você use apenas bibliotecas padrão. Mas vou mencioná-lo no título de qualquer maneira.
orlp
1
@ChristianSievers eu fiz minha própria integração para evitar a sensação ruim para usar outra pessoa :-P fórmula fechada
Luis Mendo
1
@ChristianSievers Na verdade, eu também incluiu outro formla na caixa de areia, caso você esteja = interessadas)
flawr
10

MATL , 31 bytes

0:1e-3:1lyG^-lG/^v!d|G^!slG/^sE

Experimente online! Ou verifique todos os casos de teste .

Explicação

Isso gera as coordenadas x , y de um quarto do círculo unitário amostrado em 1001 pontos com a etapa 0,001 em x . O comprimento do quarto de círculo é aproximado pelo da linha poligonal que passa por esses pontos; isto é, a soma dos comprimentos dos 1000 segmentos. Naturalmente, o comprimento é calculado de acordo com p-norm. Multiplicar o resultado por 2 fornece o comprimento aproximado de meio círculo, ou seja, pi.

0:1e-3:1   % Push [0 0.001 0.002 ... 0.999 1]. These are the x coordinates of
           % the vertices of the polygonal line that will approximate a quarter
           % of the unit circle
l          % Push 1
y          % Duplicate [0 0.001 0.002 ... 0.999 1] onto the top of the stack.
G          % Push input, p
^          % Element-wise power: gives [0^p 0.001^p ... 1^p]
-          % Element-wise subtract from 1: gives [1-0^p 1-0.001^p ... 1-1^p]
lG/        % Push 1, push p, divide: gives 1/p
^          % Element-wise power: gives [(1-0^p)^(1/p) (1-0.001^p)^(1/p) ...
           % ... (1-1^p)^(1/p)]. These are the y coordinates of the vertices
           % of the polygonal line
v          % Concatenate vertically into a 2×1001 matrix. The first row contains
           % the x coordinates and the second row contains the y coordinates
!          % Transpose
d|         % Compute consecutive differences down each column. This gives a
           % 1000×2 matrix with the x and y increments of each segment. These
           % increments will be referred to as Δx, Δy
G          % Push p
^          % Element-wise power
!          % Transpose
s          % Sum of each column. This gives a 1×1000 vector containing
           % (Δx)^p+(Δy)^p for each segment
lG/        % Push 1/p
^          % Element-wise power. This gives a 1×1000 vector containing 
           % ((Δx)^p+(Δy)^p)^(1/p) for each segment, that is, the length of 
           % each segment according to p-norm
s          % Sum the lenghts of all segments. This approximates the length of
           % a quarter of the unit circle
E          % Multiply by 2. This gives the length of half unit circle, that is,
           % pi. Implicitly display
Luis Mendo
fonte
8

Mathematica, 49 46 bytes

3 bytes salvos devido a alefalpha .

2NIntegrate[(1+(a^-#-1)^(1-#))^(1/#),{a,0,1}]&

Função anônima. Pega um número como entrada e retorna um número como saída.

LegionMammal978
fonte
1
2NIntegrate[(1+(a^-#-1)^(1-#))^(1/#),{a,0,1}]&
Alephalpha
5

PARI / GP, 48 43 bytes

É fácil depois que o @orlp encontra a fórmula e a versão do @ alephalpha salva 5 bytes:

p->2*intnum(u=0,1,(1+(u^-p-1)^(1-p))^(1/p))

Para adicionar algo um pouco útil, vamos calcular o pque obtemos 3.2:

? f=p->2*intnum(u=0,1,(1+(u^-p-1)^(1-p))^(1/p));
? solve(p=1,2,f(p)-3.2)
%2 = 1.623002382384469009676324702

Modo de usar correto

Enquanto o código fornece resultados muito mais precisos do que o desafio exige, ele pode ser facilmente aprimorado muito: se substituirmos o limite superior de integração 1por [1,1/p-1](fornecendo o que o manual chama de expoente de singularidade), todos os dígitos mostrados f(2)concordam Pi. Isso ainda é verdade se aumentarmos a precisão para 100 (tipo \p100).

No entanto, após essa alteração, o solvecálculo não funcionou mais. Alterei o termo interno para lidar explicitamente com o caso u=0e também mudei para um computador diferente com uma versão mais nova do PARI e 64 bits (o que implica uma precisão padrão mais alta).

Aqui está o cálculo aprimorado do pvalor para Pi=3.2, e também vamos dar uma olhada no Pi real:

? f=p->2*intnum(u=0,[1,1/p-1],if(u,(1+(u^-p-1)^(1-p))^(1/p),0));
? f(2)
%2 = 3.1415926535897932384626433832795028842
? Pi
%3 = 3.1415926535897932384626433832795028842
? solve(p=1,2,f(p)-3.2)
%4 = 1.6230023823844690096763253745604419761
Peneiradores cristãos
fonte
p->2*intnum(u=0,1,(1+(u^-p-1)^(1-p))^(1/p))
Alephalpha
0

JavaScript (ES7), 80 bytes

Com base na resposta do orlp . Essa implementação de JS é bastante lenta. Você pode tentar i=1e-7(ou até mais) uma aproximação mais rápida.

Nota : Isso se destina basicamente apenas ao Chrome e Edge. Uma versão equivalente do ES6 usada Math.pow()no Firefox 50.1 parece ser muito mais lenta.

Edit : De acordo com Neil, isso também deve funcionar bem no Firefox 52.

f=
p=>{for(i=5e-8,s=x=0;(x+=i)<1;)s+=i*(x**(1-p)+(1-x)**(1-p))**(1/p);return 2/p*s}

console.log(f(1).toFixed(3))
console.log(f(2).toFixed(3))
console.log(f(1.623).toFixed(3))

Arnauld
fonte
A versão ES7 parecia bastante animada quando tentei usar o Firefox 52 (não a medi cientificamente, mas parecia a mesma velocidade do Chrome; o Edge congelou em mim).
Neil
@ Neil Obrigado pelo seu feedback. Atualizado em conformidade.
Arnauld