, , . n
.
f
( "FNs" ), n
.- f th (f-1) st FNs,
m
f th FN. m >= n
(f-1) st FN , (f-1) st FN n
, f th FN FN, n
.m < n
f th FN , n
, FN n
.
f
.
AVG_FNs_PER_DIGIT = 4.784971966781667
def first_fibonacci_with_n_digits(n)
return [1, 1] if n == 1
idx = (n * AVG_FNs_PER_DIGIT).round
fn, prev_fn = fib(idx)
fn.to_s.size >= n ? fib_down(n, fn, prev_fn, idx) : fib_up(n, fn, prev_fn, idx)
end
def fib(idx)
a = 1
b = 2
(idx - 2).times {a, b = b, a + b }
[b, a]
end
def fib_up(n, b, a, idx)
loop do
a, b = b, a + b
idx += 1
break [idx, b] if b.to_s.size == n
end
end
def fib_down(n, b, a, idx)
loop do
a, b = b - a, a
break [idx, b] if a.to_s.size == n - 1
idx -= 1
end
end
:
, .
n.digits.size
n.to_s.size
? , .
def use_to_s(ndigits)
case ndigits
when 1
[1, 1]
else
a = 1
b = 2
idx = 3
loop do
break [idx, b] if b.to_s.length == ndigits
a, b = b, a + b
idx += 1
end
end
end
def use_digits(ndigits)
case ndigits
when 1
[1, 1]
else
a = 1
b = 2
idx = 3
loop do
break [idx, b] if b.digits.size == ndigits
a, b = b, a + b
idx += 1
end
end
end
require 'fruity'
def test(ndigits)
nfibs, last_fib = use_to_s(ndigits)
puts "\nndigits = #{ndigits}, nfibs=#{nfibs}, last_fib=#{last_fib}"
compare do
try_use_to_s { use_to_s(ndigits) }
try_use_digits { use_digits(ndigits) }
try_estimate { first_fibonacci_with_n_digits(ndigits) }
end
end
test 20
ndigits = 20, nfibs=93, last_fib=12200160415121876738
Running each test 128 times. Test will take about 1 second.
try_estimate is faster than try_use_to_s by 2x ± 0.1
try_use_to_s is faster than try_use_digits by 80.0% ± 10.0%
test 100
ndigits = 100, nfibs=476, last_fib=13447...37757 (90 digits omitted)
Running each test 16 times. Test will take about 4 seconds.
try_estimate is faster than try_use_to_s by 5x ± 0.1
try_use_to_s is faster than try_use_digits by 10x ± 1.0
test 500
ndigits = 500, nfibs=2390, last_fib=13519...63145 (490 digits omitted)
Running each test 2 times. Test will take about 27 seconds.
try_estimate is faster than try_use_to_s by 9x ± 0.1
try_use_to_s is faster than try_use_digits by 60x ± 1.0
test 1000
ndigits = 1000, nfibs=4782, last_fib=10700...27816 (990 digits omitted)
Running each test once. Test will take about 1 minute.
try_estimate is faster than try_use_to_s by 12x ± 10.0
try_use_to_s is faster than try_use_digits by 120x ± 100.0
:
- "try_estimate" , ;
to_s
, digits
.
, FN, , , :
- 20 : 96 93
- 100 : 479 476
- 500 : 2392 2390
- 1000 : 4785 4782
3, 3 FN .
, " ", - AVG_FNs_PER_DIGIT
, FN, .
. (Wiki FN.)
, 7 FN ( ) ; FN 4 5 FN (.. 4, 5). , , , FN n
n >= 2
, 4*n
th FN. n = 1000
4000. (, 4882- - , 1000 .) , 4000 FN. .
n
, 10**n...10**(n+1)
(n
- ), 5 FN, , 4 FN, .
LOG_10 = Math.log(10)
GR = (1 + Math.sqrt(5))/2
LOG_GR = Math.log(GR)
RATIO_5to4 = (LOG_10 - 4*LOG_GR)/(5*LOG_GR - LOG_10)
GR
- .
n- n 4 , 4 FN, n 5 - , 5 FN. FN (n 4 * 4 + n 5 * 5)/(n 4 + n 5 > ). n 5/n 4 RATIO_5to4
, n 5 RATIO_5to4
* n 4 ( ). n 5,
b = 1/(1 + RATIO_5to4)
, FN n-
avg = b * 4 + (1-b) *5
If it fn
is the first FN having decimal numbers n
, the number of FNs in the sequence before switching on fn
may be close to
n * avg
If, for example, the index score of the first FN with 1000 decimal digits will be 1000 * 4.784971966781667).round #=> 4785
.