i = 3 = 2


37

无限系列视频的启发。

介绍

Pi定义为圆周与圆直径之比。但是如何定义一个圆呢?通常,圆被定义为到中心点的距离恒定的点(假设中心位于(0,0))。下一个问题是:我们如何定义距离?以下我们考虑距离的不同概念(由Lp-norms 引起):

给定一个范数(=测量长度的东西),我们可以很容易地构造一个距离(=两点之间的距离),如下所示:

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

欧几里得范式由下式给出:

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

这也称为L2范数。其他Lp范数是通过将2上面公式中的替换为1到无穷大之间的其他值来构造的:

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

这些不同规范的单位圆具有截然不同的形状:

挑战

给定一个p >= 1,计算Lp圆相对于- Lp范数的周长与直径之比,精度为四个有效数字。

测试用例

我们可以将其用于p,q1 = 1/p + 1/q我们获得相同的比率LpLq标准比率。此外,由于p = q = 2该比率最小,并且p = 1, q = infinity我们得到的比率为4,因此比率始终在pi和之间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
这些形状称为Lamé曲线或超椭圆形,并且即使范数本身不存在,也存在0 < p <1的情况(因为它违反了三角形不等式)。维基百科上有关超级椭圆的文章包括该区域的封闭表格。
尼尔

@Neil但是,我们确实需要考虑周长,而不是面积,据我所知,周长只能通过弧长积分计算。
瑕疵

7
抱歉,等到我阅读完这些内容后,我已经忘记了这个问题的要求。
尼尔

2
可爱的挑战!
路易斯·门多

1
有趣的是,面积公式(A = πr²)不适用于p ≠ 2
Mego

Answers:


12

Python + Scipy,92个字节

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

公式来自这个math.SE问题


当用这种方法测试一个实现时,由于的奇异x=1,我在该方法的收敛性上遇到了麻烦。
瑕疵

Scipy不属于Python标准库。也许切换到Sage?
busukxuan

2
@busukxuan PPCG上没有要求,只能使用标准库。但是我还是会在标题中提到它。
orlp

1
@ChristianSievers我进行了自己的集成,以避免因为使用别人的封闭式公式而感到不适:-P
Luis Mendo

1
@ChristianSievers我实际上还在沙箱中添加了另一个formla,以防您感兴趣=)
更加虚假的

10

MATL,31个字节

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

在线尝试!验证所有测试用例

说明

这将生成x的y坐标,该坐标是四分之一圆的xy坐标,在1001个点处采样,步长为x的 0.001 。四分之一圆的长度近似为通过这些点的折线的长度;即1000个段的长度之和。长度当然是根据p-norm 计算的。将结果乘以2得到大约半个圆的长度,即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字节

由于alephalpha节省了3个字节。

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

匿名函数。将数字作为输入并返回数字作为输出。


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

5

PARI / GP,48个 43字节

@orlp找到公式后很容易,@ alephalpha的版本保存5个字节:

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

为了添加一些有用的东西,让我们计算p得到的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

正确用法

尽管代码给出的结果比挑战要求要精确得多,但可以轻松地进行很多改进:如果我们1[1,1/p-1](给出手册中称为奇异指数的)替换积分上限,则所有显示的数字均与f(2)一致Pi。如果将精度提高到100(类型\p100),这仍然是正确的。

但是,此更改之后,solve计算不再起作用。我更改了内部术语以明确处理案件u=0,还更改为另一台计算机,该计算机使用更新的PARI版本和64位(这意味着更高的默认精度)。

这是对的p值的改进计算Pi=3.2,让我们也看看真实的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个字节

基于orlp的答案。此JS的执行速度很慢。您可能想尝试i=1e-7(甚至更高)以获得更快的近似值。

注意:这基本上仅适用于Chrome和Edge。Math.pow()在Firefox 50.1上使用的等效ES6版本似乎慢得多。

编辑:根据尼尔,这也应该在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))


当我使用Firefox 52尝试时,ES7版本看起来非常漂亮(我没有科学地测量它,但是它的感觉和Chrome差不多,但Edge冻结了我)。
尼尔

@Neil感谢您的反馈。相应地更新。
Arnauld
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.