斐波那契數列
如果沒聽說過 斐波那契數列,那一定聽說過黃金分割,數列樣式:
0,1,1,2,3,5,8,13…
規律:
num3 = num2 + num1
5 = 3 + 2;
3 = 2 + 1;
2 = 1 + 1;
1 = 1 + 0;
1
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 協議》,轉載必須註明作者和本文連結