我想写一个Mathematica函数,它构造一个小于n的所有Fibonacci数的列表。此外,我希望尽可能优雅和功能(因此没有明确的循环)。
从概念上讲,我想获取自然数的无限列表,将Fib [n]映射到它上,然后在它们小于n时从该列表中获取元素。我怎样才能在Mathematica中做到这一点?
答案 0 :(得分:3)
第一部分可以在 Mathematica 中相当容易地完成。下面,我提供了两个函数nextFibonacci
,它提供的下一个斐波纳契数大于输入数(就像NextPrime
)和fibonacciList
,它提供了一个小于所有斐波那契数的列表。输入数字。
ClearAll[nextFibonacci, fibonacciList]
nextFibonacci[m_] := Fibonacci[
Block[{n},
NArgMax[{n, 1/Sqrt[5] (GoldenRatio^n - (-1)^n GoldenRatio^-n) <= m, n ∈ Integers}, n]
] + 1
]
nextFibonacci[1] := 2;
fibonacciList[m_] := Fibonacci@
Range[0, Block[{n},
NArgMax[{n, 1/Sqrt[5] (GoldenRatio^n - (-1)^n GoldenRatio^-n) < m, n ∈ Integers}, n]
]
]
现在你可以做以下事情:
nextfibonacci[15]
(* 21 *)
fibonacciList[50]
(* {0, 1, 1, 2, 3, 5, 8, 13, 21, 34} *)
第二部分虽然很棘手。您正在寻找的是Haskell类型的惰性求值,它只会在必要时进行评估(否则,您无法在内存中保留无限列表)。例如,像(在Haskell中):
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
然后允许你做
之类的事情take 10 fibs
-- [0,1,1,2,3,5,8,13,21,34]
takeWhile (<100) fibs
-- [0,1,1,2,3,5,8,13,21,34,55,89]
不幸的是,没有内置的支持你想要的东西。但是,您可以扩展 Mathematica 以实现惰性样式列表,如this answer所示,它也是implemented as a package。既然你已经拥有了所需的所有部分,我会让你自己解决这个问题。
答案 1 :(得分:3)
如果您从GitHub抓取我的Lazy package,您的解决方案就像:
一样简单Needs["Lazy`"]
LazySource[Fibonacci] ~TakeWhile~ ((# < 1000) &) // List
如果您希望稍微更实际地实现原始描述
从概念上讲,我想获取自然数的无限列表,将Fib [n]映射到它上,然后在它们小于n时从该列表中获取元素。
你可以这样做:
Needs["Lazy`"]
Fibonacci ~Map~ Lazy[Integers] ~TakeWhile~ ((# < 1000) &) // List
要证明这是完全懒惰的,请尝试前面的示例而不使用// List
。你会看到它以(相当丑陋的)形式停止:
LazyList[First[
LazyList[Fibonacci[First[LazyList[1, LazySource[#1 &, 2]]]],
Fibonacci /@ Rest[LazyList[1, LazySource[#1 &, 2]]]]],
TakeWhile[
Rest[LazyList[Fibonacci[First[LazyList[1, LazySource[#1 &, 2]]]],
Fibonacci /@ Rest[LazyList[1, LazySource[#1 &, 2]]]]], #1 <
1000 &]]
这包含一个LazyList[]
表达式,其第一个元素是您懒惰评估的表达式的第一个值,其第二个元素是如何继续扩展的说明。
持续不断地调用Fibonacci[n]
会有点低效,特别是当n
开始变大时。实际上可以构造一个惰性生成器,它将在流式传输时计算Fibonacci序列的当前值:
Needs["Lazy`"]
LazyFibonacci[a_,b_]:=LazyList[a,LazyFibonacci[b,a+b]]
LazyFibonacci[]:=LazyFibonacci[1,1]
LazyFibonacci[] ~TakeWhile~ ((# < 1000)&) // List
最后,我们可以将其概括为一个更抽象的生成函数,该函数为累加器获取初始值,List
Rule
来计算下一步的累加器值以及{ {1}} List
来计算当前累加器值的结果。
Rule
可以用它来生成Fibonacci序列,如下所示:
LazyGenerator[init_, step_, extract_] :=
LazyList[Evaluate[init /. extract],
LazyGenerator[init /. step, step, extract]]
答案 2 :(得分:1)
好的,我希望我理解这个问题。但请注意,我不是纯数学专业,我是机械工程专业的学生。但这听起来很有趣。所以我查看了公式,这就是我现在能想到的。我必须跑,但如果有错误,请告诉我,我会解决它。
此操作要求n
,然后列出小于n的所有斐波纳契数。没有循环可以找到少于n
的Fibonacci数。它使用Reduce
来求解小于n
的斐波那契数。我在结果中发言,并且还在解决方案中提出了一个复杂的乘数。
然后使用Mathematica Fibonacci
命令简单地创建所有这些数字的表格。因此,如果您输入n=20
,则会列出1,1,2,3,5,8,13
,依此类推。因为内存不足(我的电脑上只有8 GB的内存),我可以无限制地使用它。
我将n
的限制设为500000
随意编辑代码并进行更改。
Manipulate[
Module[{k, m},
k = Floor@N[Assuming[Element[m, Integers] && m > 0,
Reduce[f[m] == n, m]][[2, 1, 2]] /. Complex[0, 2] -> 0];
TableForm@Join[{{"#", "Fibonacci number" }},
Table[{i, Fibonacci[i]}, {i, 1, k}]]
],
{{n, 3, "n="}, 2, 500000, 1, Appearance -> "Labeled", ImageSize -> Small},
SynchronousUpdating -> False,
ContentSize -> {200, 500}, Initialization :>
{
\[CurlyPhi][n_] := ((1 + Sqrt[5])/2)^n;
\[Psi][n_] := -(1/\[CurlyPhi][n]);
f[n_] := (\[CurlyPhi][n] - \[Psi][n])/Sqrt[5];
}]
屏幕截图
答案 3 :(得分:0)
Fibonacci数字Fk的索引k是k=Floor[Log[GoldenRatio,Fk]*Sqrt[5]+1/2]]
,
https://en.wikipedia.org/wiki/Fibonacci_number。因此,小于或等于 n的斐波纳契数列表是
FibList[n_Integer]:=Fibonacci[Range[Floor[Log[GoldenRatio,Sqrt[5]*n+1/2]]]]