<p>好吧,如果你不能直截了当的话,是时候变聪明了,对吧?
所以我们想得到一个范围,在这个范围内可以快速计算出整个和。我会把一些伪代码,甚至不编译,可能有错误等,用它来说明。你知道吗</p>
<p>首先,让我们把这个词改写为</p>
<p>地板(100+99*x/(2<sup>52</sup>-x))</p>
<p>第一个想法-得到的范围,地板是没有变化的,因为事实上,该术语
n=<;99*x/(2<sup>52</sup>-x)<;n+1。很明显,对于这个范围,我们可以把它加到sum range_length*(100+n)上,而不需要逐项进行</p>
<pre><code>sum = 0
r_lo = 0
for k in range(0, 2*52): # LOOP OVER RANGES
r_hi = floor(2**52/(1 + 99/n))
sum += (100 + n -1)*(r_hi - r_lo)
if r_hi-r_lo == 1:
break
r_lo = r_hi + 1
</code></pre>
<p>很明显,范围大小会缩小到等于1,然后这个方法就没用了,我们爆发出来。显然,到那个时候,每一个术语都会与前一个术语相差1或更多。你知道吗</p>
<p>好的,第二个想法-同样是范围,这里的和是<a href="http://mathworld.wolfram.com/ArithmeticSeries.html" rel="nofollow noreferrer">arithmetic series</a>。首先我们要找到增量等于1的范围。那么增量等于2的范围,等等,看起来你必须找到二次方程的根,但是代码是一样的</p>
<pre><code>r_lo = pos_for_increment(1)
t_lo = ... # term at r_lo
for n in range(2, 2*52): # LOOP OVER RANGES
r_hi = pos_for_increment(n) - 1
t_hi = ... # term at r_lo
sum += (t_lo + t_hi)*(r_hi - r_lo) / 2 # arith.series sum
if r_hi > 2**52:
break
r_lo = r_hi + 1
t_lo = t_hi + n
</code></pre>
<p>也许会想些别的,但这些把戏值得一试</p>