P i = = 3. 2


37

Ispirato da questo video della serie Infinite .

introduzione

Pi è definito come il rapporto tra la circonferenza e il diametro di un cerchio. Ma come viene definito un cerchio? Di solito un cerchio è definito come i punti con distanza costante dal punto centrale (supponiamo che il centro sia a (0,0)). La prossima domanda sarebbe: come definiamo la distanza ? Di seguito stiamo prendendo in considerazione diverse nozioni di distanze (indotte dalle Lp-norm):

Data una norma (= qualcosa che misura una lunghezza ) possiamo facilmente costruire una distanza (= distanza tra due punti) come segue:

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

La norma euclidea è data da:

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

Questa è anche chiamata la norma L2 . Le altre norme Lp sono costruite sostituendo la 2formula precedente con altri valori compresi tra 1 e infinito:

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

I circoli unitari per quelle diverse norme hanno forme abbastanza distinte:

Sfida

Dato a p >= 1, calcola il rapporto tra la circonferenza e il diametro di un cerchio Lp rispetto al Lp-norm con una precisione di quattro cifre significative.

Casi test

Possiamo usarlo perché p,qcon 1 = 1/p + 1/qotteniamo lo stesso rapporto sia per Lpla Lqnorma che per la norma. Inoltre per p = q = 2il rapporto è minimo, e per p = 1, q = infinityottenere un rapporto di 4, quindi i rapporti sono sempre tra 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

2
Le forme sono conosciute come curve di Lamé o superellisse ed esistono anche per 0 < p <1, anche se la norma stessa non lo fa (perché viola la disuguaglianza del triangolo). L'articolo di Wikipedia per la superellisse include un modulo chiuso per l'area.
Neil

@Neil Dobbiamo tuttavia considerare la circonferenza, non l'area, che - per quanto ne so - può essere calcolata solo tramite un integrale di lunghezza d'arco.
flawr

7
Scusate, quando ho finito di leggerle, avevo dimenticato cosa mi aveva posto la domanda.
Neil

2
Bella sfida!
Luis Mendo,

1
È interessante notare che l'area formula ( A = πr²) non vale perp ≠ 2
Mego

Risposte:


12

Python + scipy, 92 byte

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

Formula è da questa domanda math.SE .


Quando ho testato un'implementazione con questa valutazione ho avuto problemi con la convergenza di tale approccio, a causa della singolarità di x=1, come fa la tua presentazione?
flawr

Scipy non fa parte della libreria standard di Python. Forse passare a Sage?
busukxuan,

2
@busukxuan Non è richiesto su PPCG che consenta di utilizzare solo librerie standard. Ma lo citerò comunque nel titolo.
orlp

1
@ChristianSievers Ho fatto la mia integrazione per evitare di sentirmi male per l'utilizzo della formula chiusa di qualcun altro :-P
Luis Mendo

1
@ChristianSievers In realtà ho anche incluso un altro formla nella sandbox, nel caso tu sia interessato =)
flawr

10

MATL , 31 byte

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

Provalo online! Oppure verifica tutti i casi di test .

Spiegazione

Questo genera le coordinate x , y di un quarto del cerchio unitario campionato a 1001 punti con il passo 0,001 in x . La lunghezza del quarto di cerchio è approssimata da quella della linea poligonale che passa attraverso quei punti; cioè, la somma delle lunghezze dei 1000 segmenti. La lunghezza è ovviamente calcolata secondo p-norm. Moltiplicando il risultato per 2 si ottiene la lunghezza approssimativa di mezzo cerchio, ovvero 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

8

Mathematica, 49 46 byte

3 byte salvati a causa di alephalpha .

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

Funzione anonima. Prende un numero come input e restituisce un numero come output.


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

5

PARI / GP, 48 43 byte

È facile dopo che @orlp ha trovato la formula e la versione di @ alephalpha salva 5 byte:

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

Per aggiungere qualcosa di leggermente utile, calcoliamo il pper cui otteniamo 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

Uso corretto

Sebbene il codice dia risultati molto più esatti di quanto richiesto dalla sfida, può essere facilmente migliorato molto: se sostituiamo il limite di integrazione superiore 1con [1,1/p-1](dando ciò che il manuale chiama esponente della singolarità), allora tutte le cifre mostrate f(2)concordano Pi. Questo è ancora vero se aumentiamo la precisione a 100 (tipo \p100).

Tuttavia, dopo tale modifica, il solvecalcolo non ha più funzionato. Ho cambiato il termine interno per gestire esplicitamente il caso u=0e ho anche cambiato in un altro computer con una versione PARI più recente e 64 bit (che implica una maggiore precisione predefinita).

Ecco il calcolo migliorato del pvalore per Pi=3.2, e diamo anche un'occhiata al vero Pi:

? 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

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

0

JavaScript (ES7), 80 byte

Basato sulla risposta di orlp . Questa implementazione di JS è piuttosto lenta. Potresti voler provare i=1e-7(o anche più in alto) per un'approssimazione più veloce.

Nota : questo è essenzialmente destinato solo a Chrome e Edge. Una versione ES6 equivalente che utilizza Math.pow()Firefox 50.1 sembra essere molto più lenta.

Modifica : Secondo Neil, questo dovrebbe funzionare anche su 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))


La versione ES7 mi è sembrata piuttosto brillante quando l'ho provata usando Firefox 52 (non l'ho misurata scientificamente, ma sembrava della stessa velocità di Chrome; Edge mi si è bloccato).
Neil,

@Neil Grazie per il tuo feedback. Aggiornato di conseguenza.
Arnauld,
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.