斐波那契數列 多語言實現 筆記

bigbug發表於2022-01-27

斐波那契數列

如果沒聽說過 斐波那契數列,那一定聽說過黃金分割,數列樣式:

0,1,1,2,3,5,8,13…

規律:

num3 = num2 + num1
5 = 3 + 2; 
3 = 2 + 1;
2 = 1 + 11 = 1 + 01
0
...

知道原理,就可以用程式碼實現

Kotlin

kotlin 提供了資料型別,就想試試用這個特徵

fun main(arg: Array<String>) {
   val fib = fiboData(FibonacciData(2));
   println(fib.numOne) // 結果 1
}

// 定義一個資料型別 position 記錄要返回的具體第幾位的 斐波拉契數,每次遞減
data class FibonacciData(var position: Int, val numOne: Int = 0, val numTwo: Int = 0);

fun fiboData(fib: FibonacciData = FibonacciData(0, 0, 0)): FibonacciData {
   if (fib.position <= 0) {
      return fib;
   }
   val newFibo = if (fib.numTwo <= 0) {
      FibonacciData(fib.position - 1, 0, 1)
   } else {
      FibonacciData(fib.position - 1, fib.numTwo, fib.numOne + fib.numTwo)
   }
   return fiboData(newFibo)
}

Rust

rust 語言想到了 元組 複合型別

fn main() {
    let num = fibonacci_num(10);
    println!("{}", num); // 輸出 34
}

fn fibonacci_num(position: u32) -> u32 {
    let (_, num_one, _) = fibonacci_data((position, 0, 0));
    num_one
}

fn fibonacci_data(fibo: (u32, u32, u32)) -> (u32, u32, u32) {
    let (position, num_one, num_two) = fibo;
    if position <= 0 {
        return fibo;
    }
    if num_two <= 0 {
        fibonacci_data((position - 1, 0, 1))
    } else {
        fibonacci_data((position - 1, num_two, num_one + num_two))
    }
}

寫完 rust 實現後,發現雖然換了語言,但寫出來的風格居然一模一樣,是不是可以說明:語言只是工具而已。

php

想著減少程式碼量,用遞迴,雖然有點慢,且耗效能,但算是能跑

    /**
     * 獲取指定位置的 斐波拉契數
     * @param int $position 位置
     * @return int
     */
    protected function fibonacci(int $position = 0): int
    {
        // 0,1,1,2 前面幾位需要做下特殊處理
        if ($position <= 0) {
            return 0;
        } elseif ($position <= 3) {
            return 1;
        }
        // 效率低,$position 越大,就越慢,但程式碼量少。
        return $this->fibonacci($position - 1) + $this->fibonacci($position - 2);
    }

PHP 匿名函式實現起來更方便,所以重新寫了一版,考慮到 int 儲存資料大小有限,所以用 string 來儲存,理論上不會出現資料溢位。

整型數 int 的字長和平臺有關,儘管通常最大值是大約二十億(32 位有符號)。64 位平臺下的最大值通常是大約 9E18。

/**
     * Execute the console command.
     * [環境 php7.4 + laravel 8 artisan ]
     *
     */
    public function handle()
    {
        $this->line($this->fibonacci(1000));
    }

    /**
     * 斐波拉契數
     * @param int $position 定位置
     * @return string
     */
    public function fibonacci(int $position): string
    {
        $fn = function(int $position, string $numOne = '0', string $numTwo = '0') use (&$fn) {
            if ($position <= 0) {
                return [$position, $numOne, $numTwo];
            }
            $position -= 1;
            if ((int)$numTwo <= 0) {
                return $fn($position, "0", "1");
            }
            return $fn($position, $numTwo, $this->numStrAdd($numTwo, $numOne));
        };
        return $fn($position)[1] ?? '0';
    }

    /**
     * 數值字串相加
     * @param string $numOne 第一個數
     * @param string $numTwo 第二個數
     * @return string
     */
    public function numStrAdd(string $numOne, string $numTwo): string
    {
        $numOneArr = array_reverse((array)$numOne);
        $numTwoArr = array_reverse((array)$numTwo);
        if (count($numOneArr) < count($numTwoArr)) {
            $tempArr = $numOneArr;
            $numOneArr = $numTwoArr;
            $numTwoArr = $tempArr;
            unset($tempArr);
        }

        $newNumArr = [];
        $tempNum = 0;
        foreach ($numOneArr as $k => $v) {
            $needSumNumber = $numTwoArr[$k] ?? 0;
            $v += $needSumNumber;
            $v += $tempNum;
            $tempNum = 0;
            $v = (array)(string)$v;

            $needUnSiftNum = 0;
            if (count($v) > 1) {
                $tempNum = $v[0];
                $needUnSiftNum = $v[1];
            } else {
                $needUnSiftNum = $v[0];
            }
            array_unshift($newNumArr, $needUnSiftNum);
        }
        if ($tempNum > 0) {
            array_unshift($newNumArr, $tempNum);
        }
        return implode('',$newNumArr);
    }
本作品採用《CC 協議》,轉載必須註明作者和本文連結
Less is more.

相關文章