- 注册时间
- 2007-12-28
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 12785
- 在线时间
- 小时
|
花了点时间,写了python代码。不过,我不能讲明白算法原理。主要是,不能证明我的这个算法为什么不会漏掉某些解。但是,这个代码的计算结果和楼主给出的结果完全一致,从侧面说明了我的算法的有很高的可信度。或许以后,我的这个算法被证明或者证伪。下面是源代码。今年了python比较火,这是我第一次写数值计算的Python程序。
- #!/usr/bin/python3
- # -*- coding: utf-8 -*-
- import mpmath
- from mpmath import mpf,exp,log,floor,pi
- # 全局变量,常数
- log10_2 = mpf(0) # will calc later
- # 令 a* 10^d =2^n, (1<=a<10), 已知n,d,求a
- def calc_a( n, d ):
- global log10_2
-
- # 令 a* 10^d = 2^n, (1<=a<10),
- # 两边取常用对数,
- # log10(a) + d = n*log10(2)
- # d = n*log10(2) - log10(a) = floor(n*log10(2))
- c2 = mpf(2)
- c10 = mpf(10)
- v_2pn = c2 ** n # 2^n
- d= mpmath.floor(n*log10_2)
- a = v_2pn / (c10 ** d)
- return a
- # 令 2^n = a*10^d , (0.1< a <= 1.0), 已知n,d,求a
- def calc_a1( n, d ):
- c2 = mpf(2)
- c10 = mpf(10)
- a = (c2 ** n) / (c10 ** d)
- return a
-
- def search_in_interval( base, pi_lo, pi_hi ,layer=0):
-
- (n,d) = base
- a= calc_a(n,d )
- esp= (10 ** (-mpmath.mp.dps)) * mpf("4.0") # 精度误差
-
- if a>= pi_lo and a < (pi_hi-esp):
- return base
-
- low = pi_lo / a # 放大倍数的下界
- high = pi_hi / a # 放大倍数的下界
- #print(f"\n2^{n} = {a} * 10^{d}")
- l_lo=log(low); l_hi=log(high) # 取对数,方便计算,乘除变加减
-
- # 定义一个区间 (start, end) c0
- # 因为 2^3= 0.8 * 10^1, 2^4=1.6*10^1, 所以
- # begin=(3,1,0.8), end=(4,1,1.6)
- begin=(mpf(3),mpf(1),log(mpf("0.8")))
- end =(mpf(4),mpf(1),log(mpf("1.6")))
-
- iter_count=0
- c0 = mpf(0)
- while True:
- (n0,d0,v0)=begin ; (n1,d1,v1)=end
-
- #print(f"v0:{v0}, v1:{v1}, mid_v:{mid_v}")
- l_m = v0 + v1 # l_m=log(mid)
- mid = (n0+n1,d0+d1,l_m)
-
- if l_m < l_lo and l_m < c0 :
- begin = mid # mid总是大于begin, begin 不断增大,但 begin.v0始终<=0
- elif l_m > l_hi and l_m > c0 :
- end = mid # mid总是小于end, end 不断减小,但end.v始终>=0
- else:
- break
- iter_count +=1
- #end while
-
- (n0,d0,v0)=begin; (n1,d1,v1)=end
- l_m = v0 + v1
- if l_m >= l_lo and l_m<l_hi:
- (n,d) = base
- #print("layer:", layer, ",get an result:", n+(n0+n1))
- return ( n+(n0+n1),d+(d0+d1))
-
- if n0<n1:
- base = (n+n0,d+d0)
- else:
- base = (n+n1,d+d1)
- return search_in_interval( base, pi_lo, pi_hi,layer+1 ) # 递归调用
-
- #end search_in_interval
- def question_19684(MAX_N,debug=False ):
- r0= (mpf(5.0), mpf(1.0) ) # 2^5/10^1=3.2
- print(1, 5)
- results=[r0]
-
- c10 = mpf(10)
- for i in range(2, MAX_N+1):
- v_10p_i = c10 ** (i-1) # 10^(i-1)
- tmp = floor(pi * v_10p_i)
- pi_lo = tmp/v_10p_i # 圆周率的下界
- pi_hi = (tmp+1)/v_10p_i # 圆周率的上界
-
- if debug:
- print(f"\n{i}:pi_lo={pi_lo},pi_hi = {pi_hi}")
- base = results[-1]
- res = search_in_interval(base, pi_lo, pi_hi )
- (n,d)=res # 2^n/10^d是一个非常接近于1.0的数
-
- a=calc_a(n,d)
- if debug:
- print(f"2^{n} = {a} * 10^{d}")
- s=str(n)
- if s.endswith(".0"):
- s=s[:-2]
- print(i, s)
- results.append((n,d))
- #end for
- def main():
- global log10_2
-
- MAX_N=1000
- mpmath.mp.dps = (MAX_N*2)+16
-
- c2 = mpf(2)
- c10 = mpf(10)
- log10_2 = log(c2)/log(c10)
-
- #question_19684(MAX_N,True)
- question_19684(MAX_N,False)
-
- main()
复制代码 |
|