rust-計算無限循環小數的循環週期

簡介

  • 任意的無限循環小數均可以用兩個有理數組成的分數表示;
  • 無限循環小數也是有理數

算法

因爲需求只是求出循環週期,所以不關心其小數形式。利用小學三年級計算除法的步驟。當除得的餘數重複出現時,兩次步驟之間的間隔數目即爲小數但循環週期。算法

ps: 函數傳入參數爲兩個u64.數組

code

code1

fn cycle(m:u64,n:u64) -> Option<u64>{
    use std::collections::HashMap;

    let mut residues = HashMap::new();
    let mut residue = m%n;
    let mut count:u64 = 0;
    residues.insert(residue, count);
    loop{
        count +=1;
        residue = (residue*10)%n;
        if residue == 0{
            return None;
        }
        if let Some(res) = residues.get(&residue){
            return Some(count-res);
        }
        residues.insert(residue, count);
    }
}

#[test]
fn test() {
    //1.42857 142857 142857 ...
    assert!(Some(6) == cycle(10,7));
}

code2

HashMap的好處是,hash查找的時間複雜度爲O(1),每次查詢所消耗的的時間固定。但缺點是每次查詢都須要計算一次hash值,遇到hash碰撞還會使得性能降低。總的來講比較適合循環週期較長的狀況。函數

代碼中,hash表記錄的值是這個餘數出現的序數。能夠用vec代替,則餘數出現但序數就是該數在數組中的索引。「呆?!看代碼。。。」oop

fn cycle(m:u64,n:u64) -> Option<u64>{
    let mut residues = vec![];
    let mut residue = m%n;
    residues.push(residue);
    loop{
        residue = (residue*10)%n;
        if residue == 0{
            return None;
        }
        if let Some(res) = residues.iter().position(|&item|item==residue){
            return Some((residues.len() -res) as u64);
        }
        residues.push(residue);
    }
}
相關文章
相關標籤/搜索