最近开了个新坑,学习Rust,主要是因为自己一直想学一门函数式的语言。首先我们直接用公式法计算斐波那契数列,代码如下:
use std::io;
use num::BigUint;
use num::traits::{Zero,One};
fn main() {
println!("Calculate Fibonacci sequence please type n \nand then give your n th number of sequence");
let mut input_str=String::new();
io::stdin().read_line(&mut input_str).expect("INPUT ERROR");
let n:u32=input_str.trim().parse().expect("NOT A NUMBER");
println!("the {} n th number of sequence is\n{}",n,fibonacci_cal(n));
}
fn fibonacci_cal(mut i:u32) -> BigUint
{
let mut n1:BigUint=Zero::zero();
let mut n2:BigUint=One::one();
match i {
0=> n1,
1=> n2,
_=>{
while i >=2 {
let k=n2.clone();
n2+=n1;
n1=k;
i-=1;
}
n2
}
}
}
CSDN居然没有Rust的语法高亮!(原来是有高亮的,找不到标签选没有设置就有高亮)
为了让计算时间较长方便对比我打算计算一个u128类型都装不下的数,所以我是用了num库下的BigUint类型,该类型的实际有效范围只与机器配置相关,然后我们用time命令测一下计算第200001个数的时间,当然输入我们从文件重定向过去。
斐波那契数列的计算过程可以用一个矩阵乘法来表示,而求第一二项后任意一项的过程就是反复乘以该矩阵,我们可以先求该矩阵的n次幂,然后再用第一二项乘以该矩阵,然后求幂的时候我们可以用快速幂算法,该算法在网上有大量论述,我在这里就直接贴代码了。
use std::io;
use num::BigUint;
use num::traits::{Zero,One};
fn main() {
println!("Calculate Fibonacci sequence please type n \nand then give your n th number of sequence");
let mut input_str=String::new();
io::stdin().read_line(&mut input_str).expect("INPUT ERROR");
let n:u32=input_str.trim().parse().expect("NOT A NUMBER");
println!("the {} n th number of sequence is\n{}",n,fibonacci_cal(n));
// let mx1=[BigUint::from(1u32),BigUint::from(1u32),BigUint::from(1u32),BigUint::from(2u32)];
// let mx2=mx1.clone();
// let mx3=matrix_multi(mx1,mx2);
// println!("the arr is {} {} {} {}",mx3[0],mx3[1],mx3[2],mx3[3]);
}
fn fibonacci_cal(i:u32) -> BigUint
{
let n1:BigUint=Zero::zero();
let n2:BigUint=One::one();
match i {
0=> n1,
1=> n2,
_=>{
let p=i/2;
let t=i%2;
let mx=[BigUint::from(1u32),BigUint::from(1u32),BigUint::from(1u32),BigUint::from(2u32)];
let rel_ma=matrix_fast_pow(mx,p);
let n2=if t==0 { n1*&rel_ma[0]+n2*&rel_ma[2] } else { n1*&rel_ma[1]+n2*&rel_ma[3] };
n2
}
}
}
//4*4 matrix 0 1 0 1
// 2 3 2 3
fn matrix_multi(m1:&[BigUint;4],m2:&[BigUint;4])->[BigUint;4]
{
// let mut rel_matrix=[Zero::zero(),Zero::zero(),Zero::zero(),Zero::zero()];
let mut rel_matrix:[BigUint;4]=Default::default();
rel_matrix[0]=&m1[0]*&m2[0]+&m1[1]*&m2[2];
rel_matrix[1]=&m1[0]*&m2[1]+&m1[1]*&m2[3];
rel_matrix[2]=&m1[2]*&m2[0]+&m1[3]*&m2[2];
rel_matrix[3]=&m1[2]*&m2[1]+&m1[3]*&m2[3];
rel_matrix
}
fn matrix_fast_pow(mut m:[BigUint;4],n:u32)->[BigUint;4]
{
let mut rel_mx=[BigUint::from(1u32),BigUint::from(0u32),BigUint::from(0u32),BigUint::from(1u32)];
let mut bi=1 as u32;
loop {
if n&bi!=0 { rel_mx=matrix_multi(&rel_mx,&m);}
m=matrix_multi(&m,&m);
bi=bi<<1;
if bi>n {break;}
else if bi==1u32<<31 {rel_mx=matrix_multi(&rel_mx,&m);break;}
}
rel_mx
}
7s多变1s这就是算法的力量