Ada 程式設計/演算法/第 6 章
以下程式碼是 斐波那契數列示例 的實現。
...
為了計算斐波那契數列,不需要負值,因此我們定義了一個從 0 開始的整數型別。定義了整數型別後,您可以計算到 Fib (87)。Fib (88) 將導致 Constraint_Error。
typeInteger_Typeisrange0 .. 999_999_999_999_999_999;
您可能會注意到,原始示例中沒有 assert (n >= 0) 的等效項。Ada 將在函式呼叫之前測試引數的正確性。
functionFib (n : Integer_Type)returnInteger_Typeisbeginifn = 0thenreturn0;elsifn = 1thenreturn1;elsereturnFib (n - 1) + Fib (n - 2);endif;endFib; ...
...
對於此實現,我們需要一種特殊的快取型別,它還可以儲存 -1 作為“未計算”標記
typeCache_Typeisrange-1 .. 999_999_999_999_999_999;
用於計算斐波那契數列的實際型別繼續從 0 開始。由於它是子型別 的快取型別,Ada 將自動在這兩者之間進行轉換。(轉換當然會檢查有效性)
subtypeInteger_TypeisCache_Typerange0 .. Cache_Type'Last;
為了知道快取需要多大,我們首先從命令列讀取實際值。
Value : constant Integer_Type :=
Integer_Type'Value (Ada.Command_Line.Argument (1));
快取陣列從元素 2 開始,因為 Fib (0) 和 Fib (1) 是常數,並以我們要計算的值結束。
typeCache_Arrayisarray(Integer_Typerange2 .. Value)ofCache_Type;
快取被初始化為快取型別的第一個有效值——即 -1。
F : Cache_Array := (others => Cache_Type'First);
以下是實際演算法。
functionFib (N : Integer_Type)returnInteger_TypeisbeginifN = 0orelseN = 1thenreturnN;elsifF (N) /= Cache_Type'FirstthenreturnF (N);elseF (N) := Fib (N - 1) + Fib (N - 2);returnF (N);endif;endFib; ...
此實現忠實於 演算法 書籍中的原始實現。但是,在 Ada 中,您通常會以略微不同的方式進行
當您使用稍大的陣列時,該陣列還儲存元素 0 和 1 並將其初始化為正確的值
typeCache_Arrayisarray(Integer_Typerange0 .. Value)ofCache_Type; F : Cache_Array := (0 => 0, 1 => 1,others=> Cache_Type'First);
然後您可以刪除第一個if 路徑。
ifN = 0orelseN = 1thenreturnN; elsifF (N) /= Cache_Type'Firstthen
這將節省大約 45% 的執行時間 (在 Linux i686 上測量),同時只需要在快取陣列中新增兩個元素。
此版本看起來與 WikiCode 中的原始版本完全一樣。
typeInteger_Typeisrange0 .. 999_999_999_999_999_999;functionFib (N : Integer_Type)returnInteger_TypeisU : Integer_Type := 0; V : Integer_Type := 1;beginforIin2 .. NloopCalculate_Next :declareT :constantInteger_Type := U + V;beginU := V; V := T;endCalculate_Next;endloop;returnV;endFib;
您的 Ada 編譯器不支援 64 位整數嗎?然後您可以嘗試使用 十進位制數。使用十進位制數會導致程式變慢 (大約需要三倍的時間),但結果將相同。
以下示例展示瞭如何定義合適的十進位制型別。請嘗試位數 和範圍 引數,直到您從 Ada 編譯器中獲得最佳結果。
typeInteger_Typeisdelta1.0digits18range0.0 .. 999_999_999_999_999_999.0;
您應該知道,浮點數不適合計算斐波那契數列。當計算的數字過大時,它們不會報告錯誤條件——相反,它們會失去精度,這會使結果毫無意義。
