学习Winsock编程,用TCP协议收发文件是必不可少的一个实践环节,而计算收发百分比的一行代码,很多人都写不对。
假设我们用DWORD(unsigned long)来表示文件长度,则长度的最大值是232-1,也就是4GB。虽然Win32 API能够返回两个DWORD表示长度,但是为了简便,我们还是原意接收4GB的人为限制。以下我们的讨论基于这个前提。
通常我们会使用一个DWORD表示length,一个DWORD表示pos。为了避免使用浮点数,很多人会这样写
DWORD percent = pos * 100 / length;
之所以把100乘在前面,是因为这个除法是整数除法,不这样的话,percent将永远是0。这样以来,pos*100便有了一个限制,它不能溢出,也就是不能大于232-1。这样,如果我们传送大于4GB/100=40MB的文件,这个percent就会计算错误。
显然不能先做乘法,但还要不使用浮点运算,怎么写才对呢?
DWORD percent = 0;
if (pos > 0) percent = 100 / (length / pos);
开始我以为这样写是很好的办法,结果试一试就知道25%->33%->50%->100%,分别是分母为4,3,2,1的结果,这也不是正确的写法。
看来,不加长字长是没什么好办法了。好在windows支持8字节大整数运算,所以这样写是对的:
DWORD percent = (DWORD)((ULONGLONG)pos * 100 / length);
两次转型,不过也确实没什么别的办法,如果没有8字节整数,与其自己写还真不如用浮点运算得了。