最近想學習Libra數字貨幣的MOVE語言,發現它是用Rust編寫的,因此先補一下Rust的基礎知識。學習了一段時間,發現Rust的學習曲線很是陡峭,不過仍有快速入門的辦法。git
學習任何一項技能最怕沒有反饋,尤爲是學英語、學編程的時候,必定要「用」,學習編程時有一個很是有用的網站,它就是「歐拉計劃」,網址: https://projecteuler.netgithub
英文若是不過關,能夠到中文翻譯的網站:
http://pe-cn.github.io/編程
這個網站提供了幾百道由易到難的數學問題,你能夠用任何辦法去解決它,固然主要還得靠編程,編程語言不限,論壇裏已經有Java、C#、Python、Lisp、Haskell等各類解法,固然若是你直接用google搜索答案就沒任何樂趣了。編程語言
學習Rust最好先把基本的語法和特性看過一遍,而後就能夠動手解題了,解題的過程就是學習、試錯、再學習、掌握和鞏固的過程,學習進度會大大加快。函數
問題描述:學習
單位分數指分子爲1的分數。優化
1/6= 0.1(6) 表示0.166666…,括號內表示有一位循環節。網站
1/7= 0.(142857),1/7有六位循環節。google
找出正整數d < 1000,其倒數的十進制表示小數部分有最長的循環節。.net
經過手算找到規律,
再找一個分母大於10的:
再找一個能除盡的:
能夠發現幾個特色:
1)分子爲1,表示一開始的餘數爲1
2)餘數爲0時,表示能夠除盡,循環要終止
3)當餘數重複出現時,表示找到了循環節,2個重複出現的位置就是循環節
按照這個邏輯,循環節的長度能夠求出,這裏用兩個向量分別存儲餘數remainders和商digits。
fn reciprocal_cycle(d: u32) -> u32 { let mut remainders : Vec<u32> = vec![1]; //餘數 let mut digits : Vec<u32> = vec![]; //商 let mut numerator = 1; //分子 while numerator != 0 { digits.push(numerator * 10 / d); numerator = numerator * 10 % d; //餘數 let pos = remainders.iter().position(|&x| x==numerator); match pos { Some(x) => { //餘數重複出現時 return (digits.len() - x) as u32; } None => { remainders.push(numerator); } } } 0 //除盡的時候,表示循環節爲0 }
這裏在向量裏查找一個元素的位置索引時用了position函數,返回是一個Option
主程序就簡單了:
let mut max_cycle: u32 = 0; for n in 2..1000 { let rc = reciprocal_cycle(n); if rc > max_cycle { println!("n={} cycle={}", n, rc); max_cycle = rc; } } println!("max reciprocal cycle: {}", max_cycle);
優化:實際上商並不須要存儲,能夠減小一個向量,求循環節的函數還能夠精簡一下。
fn reciprocal_cycle(d: u32) -> u32 { let mut remainders : Vec<u32> = vec![1]; //餘數 let mut numerator = 1; //分子 while { numerator = numerator * 10 % d; numerator != 0} { let pos = remainders.iter().position(|&x| x==numerator); match pos { Some(x) => { //餘數重複出現時 return (remainders.len() - x) as u32; } None => { remainders.push(numerator); } } } 0 //除盡的時候,表示循環節爲0 }