之前的一些答案使用时间或空间复杂度 O(n) 的方法,其中 n 是将被接受的最大“小数”。相比之下,以下方法在时间上是 O(sqrt(n)),在空间上是 O(1)。
假设正实数r = x + y
,其中x=floor(r)
和0 ≤ y < 1
。我们想r
通过一个数字来近似的形式a + √b
。如果x+y ≈ a+√b
then x+y-a ≈ √b
,那么√b ≈ h+y
对于一些整数偏移量h
,并且b ≈ (h+y)^2
。为了使 b 成为整数,我们希望最小化(h+y)^2
所有符合条件的小数部分h
。最多有 的√n
合格值h
。请参阅以下 python 代码和示例输出。
import math, random
def findb(y, rhi):
bestb = loerror = 1;
for r in range(2,rhi):
v = (r+y)**2
u = round(v)
err = abs(v-u)
if round(math.sqrt(u))**2 == u: continue
if err < loerror:
bestb, loerror = u, err
return bestb
#random.seed(123456) # set a seed if testing repetitively
f = [math.pi-3] + sorted([random.random() for i in range(24)])
print (' frac sqrt(b) error b')
for frac in f:
b = findb(frac, 12)
r = math.sqrt(b)
t = math.modf(r)[0] # Get fractional part of sqrt(b)
print ('{:9.5f} {:9.5f} {:11.7f} {:5.0f}'.format(frac, r, t-frac, b))
(注 1:此代码为演示形式;参数为findb()
,y
小数部分r
,和rhi
,最大小数的平方根。您可能希望更改参数的用法。注 2:代码行
if round(math.sqrt(u))**2 == u: continue
防止findb()
返回 的完美平方值b
,但值 b=1 除外,因为没有完美平方可以提高 b=1 提供的精度。)
示例输出如下。中间省略了大约十几行。第一个输出行显示此过程产生b=51
表示 的小数部分pi
,这与其他一些答案中报告的值相同。
frac sqrt(b) error b
0.14159 7.14143 -0.0001642 51
0.11975 4.12311 0.0033593 17
0.12230 4.12311 0.0008085 17
0.22150 9.21954 -0.0019586 85
0.22681 11.22497 -0.0018377 126
0.25946 2.23607 -0.0233893 5
0.30024 5.29150 -0.0087362 28
0.36772 8.36660 -0.0011170 70
0.42452 8.42615 0.0016309 71
...
0.93086 6.92820 -0.0026609 48
0.94677 8.94427 -0.0024960 80
0.96549 11.95826 -0.0072333 143
0.97693 11.95826 -0.0186723 143
在程序末尾添加以下代码后,还会出现如下所示的输出。这显示了 pi 小数部分的更接近的近似值。
frac, rhi = math.pi-3, 16
print (' frac sqrt(b) error b bMax')
while rhi < 1000:
b = findb(frac, rhi)
r = math.sqrt(b)
t = math.modf(r)[0] # Get fractional part of sqrt(b)
print ('{:11.7f} {:11.7f} {:13.9f} {:7.0f} {:7.0f}'.format(frac, r, t-frac, b,rhi**2))
rhi = 3*rhi/2
frac sqrt(b) error b bMax
0.1415927 7.1414284 -0.000164225 51 256
0.1415927 7.1414284 -0.000164225 51 576
0.1415927 7.1414284 -0.000164225 51 1296
0.1415927 7.1414284 -0.000164225 51 2916
0.1415927 7.1414284 -0.000164225 51 6561
0.1415927 120.1415831 -0.000009511 14434 14641
0.1415927 120.1415831 -0.000009511 14434 32761
0.1415927 233.1415879 -0.000004772 54355 73441
0.1415927 346.1415895 -0.000003127 119814 164836
0.1415927 572.1415909 -0.000001786 327346 370881
0.1415927 911.1415916 -0.000001023 830179 833569