你以爲你真的會計算進度嗎?

現有一需求,計算拷貝文件的進度。假設已知文件總大小t字節,已拷貝了n字節。

對於如此簡單的需求,大多數人會第一時間這樣實現

  1. int progress(int t, int n) 
  2.     //已完成除以總大小 
  3.     return n/t*100
  4. }

很抱歉,這樣實現你將發現它會只有兩個值——0和100。原因是,當一個整數除以另一整數,如果小於0,則 向下取整爲0,0*100自然也是等於0。

有人於是用以下實現

  1. int progress(int t, int n) 
  2.     return 100*n/t; 
  3. }

這種方式在多數情況下工作比較理想,直到某一天,你遇到一個大於2G的文件,你發現傳統的32位整數表示不了了。 於是採用64位

  1. int progress(off_t t, off_t n) 
  2.     return 100*n/t; 
  3. }

off_t是個不錯的寫法,它在不同系統上有不同的定義。可是,你又發現有人給你傳了一個大於文件總大小的值,計算的值超過100了!再改改

  1. int progress(int t, int n) 
  2.    return min(100*n/t, 100); 
  3. }

不過既然有特殊情況,萬一傳過來是負的怎麼辦?再判斷一下咯

  1. int progress(int t, int n) 
  2.    if (t < 0 || n < 0
  3.        return 0
  4.    return min(100*n/t, 100); 
  5. }

應該沒問題了吧。但是,你可能沒料到,一個足夠大的文件,即使64位下,100*n也可能溢出!TMD,真的要逼我祭出絕殺武器嗎

  1. int progress(int t, int n) 
  2.    if (t < 0 || n < 0
  3.        return 0
  4.    double p = double(n); 
  5.    p /= t; 
  6.    p *= 100
  7.    return min(int(p), 100); 
  8. }

應該行了吧,老子都用到雙精度了。

呃……最後一句int(p)是個隱患,尼瑪能保證p不超過64位整形?

  1. int progress(int t, int n) 
  2.    if (t < 0 || n < 0
  3.        return 0
  4.    double p = double(n); 
  5.    p /= t; 
  6.    p *= 100
  7.    if (p > 99.0
  8.        return 100
  9.    else 
  10.       return int(p); 
  11. }

相安無事了很長時間,直到一天,一個腦殘的傢伙給了一個大小爲0的文件


程序員真的是一件很危險的職業……


作者:annidy
版權所有,轉載請註明出處 blog.csdn.net/ani_di


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章