3

n未満のすべてのフィボナッチ数のリストを作成する数学関数を作成したいと思います。さらに、これを可能な限りエレガントかつ機能的に(明示的なループなしで)実行したいと思います。

概念的には、自然数の無限のリストを取得し、それにFib [n]をマップしてから、n未満の要素をこのリストから取得したいと思います。Mathematicaでこれを行うにはどうすればよいですか?

4

4 に答える 4

3

私のLazyパッケージをGitHubから入手すると、ソリューションは次のように簡単になります。

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[]最初の要素が遅延評価している式の最初の値であり、2番目の要素が展開を続行する方法の指示である式で構成されます。

改善

特に大きくなり始めFibonacci[n]たときに、常に電話をかけ続けるのは少し非効率的です。nストリーミング時にフィボナッチ数列の現在の値を計算するレイジージェネレーターを構築することは実際に可能です。

Needs["Lazy`"]

LazyFibonacci[a_,b_]:=LazyList[a,LazyFibonacci[b,a+b]]
LazyFibonacci[]:=LazyFibonacci[1,1]

LazyFibonacci[] ~TakeWhile~ ((# < 1000)&) // List

最後に、これをより抽象的な母関数に一般化して、アキュムレータの初期値を取得しますList。aof Rulesは次のステップのListアキュムレータRule値を計算し、aofsは現在のアキュムレータ値から結果を計算します。

LazyGenerator[init_, step_, extract_] := 
 LazyList[Evaluate[init /. extract], 
  LazyGenerator[init /. step, step, extract]]

そして、それを使用して、次のようにフィボナッチ数列を生成できます。

LazyGenerator[{1, 1}, {a_, b_} :> {b, a + b}, {a_, b_} :> a]
于 2012-12-28T23:24:29.170 に答える
3

最初の部分はMathematicaでかなり簡単にできます.以下にnextFibonacci、入力数値より大きい次のフィボナッチ数を提供する 2 つの関数 ( と同様NextPrime) とfibonacciList、入力数値より小さいすべてのフィボナッチ数のリストを提供する 2 つの関数を提供します。

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} *)

ただし、2 番目の部分はトリッキーです。あなたが探しているのは、必要な場合にのみ評価する 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を拡張して遅延スタイル リストを実装できます。これはパッケージとしても実装されています。必要な部品がすべて揃ったので、自分で作業してもらいます。

于 2012-12-28T18:40:20.117 に答える
1

わかりました、私は質問を理解したと思います. ただし、私は純粋な数学専攻ではなく、機械工学の学生です。しかし、これは面白そうでした。そこで式を調べたところ、これが今思いつくことができます。実行する必要がありますが、バグがある場合はお知らせください。修正します。

nこの操作は、n 未満のすべてのフィボナッチ数を要求してリストします。より小さいフィボナッチ数がいくつあるかを調べるループはありませんnReduce未満のフィボナッチ数を解くために使用しnます。私は結果の床を取り、また解で思いついた定数を捨てました。これは複素乗数です。

次に、MathematicaFibonacciコマンドを使用してこれらすべての数値の表を作成します。入力n=20すると、リスト1,1,2,3,5,8,13などが表示されます。メモリが足りなくなったので、無限に実行できました(PCには8 GBのRAMしかありません)。

nコードを編集して500000変更するのは自由です。

Mathematica グラフィックス

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];
   }]

スクリーンショット

Mathematica グラフィックス

于 2012-12-28T17:28:08.320 に答える