现有一需求,计算拷贝文件的进度。假设已知文件总大小t字节,已拷贝了n字节。
对于如此简单的需求,大多数人会第一时间这样实现
- int progress(int t, int n)
- {
- //已完成除以总大小
- return n/t*100;
- }
很抱歉,这样实现你将发现它会只有两个值——0和100。原因是,当一个整数除以另一整数,如果小于0,则 向下取整为0,0*100自然也是等于0。
有人于是用以下实现
- int progress(int t, int n)
- {
- return 100*n/t;
- }
这种方式在多数情况下工作比较理想,直到某一天,你遇到一个大于2G的文件,你发现传统的32位整数表示不了了。 于是采用64位
- int progress(off_t t, off_t n)
- {
- return 100*n/t;
- }
off_t是个不错的写法,它在不同系统上有不同的定义。可是,你又发现有人给你传了一个大于文件总大小的值,计算的值超过100了!再改改
- int progress(int t, int n)
- {
- return min(100*n/t, 100);
- }
不过既然有特殊情况,万一传过来是负的怎么办?再判断一下咯
- int progress(int t, int n)
- {
- if (t < 0 || n < 0)
- return 0;
- return min(100*n/t, 100);
- }
应该没问题了吧。但是,你可能没料到,一个足够大的文件,即使64位下,100*n也可能溢出!TMD,真的要逼我祭出绝杀武器吗
- int progress(int t, int n)
- {
- if (t < 0 || n < 0)
- return 0;
- double p = double(n);
- p /= t;
- p *= 100;
- return min(int(p), 100);
- }
应该行了吧,老子都用到双精度了。
呃……最后一句int(p)是个隐患,尼玛能保证p不超过64位整形?
- int progress(int t, int n)
- {
- if (t < 0 || n < 0)
- return 0;
- double p = double(n);
- p /= t;
- p *= 100;
- if (p > 99.0)
- return 100;
- else
- return int(p);
- }
相安无事了很长时间,直到一天,一个脑残的家伙给了一个大小为0的文件
程序员真的是一件很危险的职业……
作者:annidy
版权所有,转载请注明出处 blog.youkuaiyun.com/ani_di