>我目前正在编写一个小下载管理器,当我尝试以百分比计算下载进度时,我得到了一个有趣的输出。这是我用来计算它的:
int progress = (byte_counter * 100) / size;
System.out.println("("+byte_counter+" * 100) = "+(byte_counter * 100)
+" / "+size+" = "+progress);
byte-counter
是一个 int(它计算从InputStream
读取的总字节数),size
是下载文件的长度(以字节为单位)。
这适用于小型下载。但是当我到达更大的文件(40MB)时,它开始制造有趣的事情。计算的输出如下所示:
[...]
(21473280 * 100) = 2147328000 / 47659008 = 45
(21474720 * 100) = 2147472000 / 47659008 = 45
(21476160 * 100) = -2147351296 / 47659008 = -45
(21477600 * 100) = -2147207296 / 47659008 = -45
[...]
我不知道为什么,但计算结果为负数。由于一个普通的整数应该可以处理到231-1的数字,这不应该是问题的根源。但是我错过了什么?
请参阅 http://en.wikipedia.org/wiki/Arithmetic_overflow
要在 Java 中修复,请尝试改用long
。
int progress = (int) ((byte_counter * 100L) / size);
或操作顺序相反
int progress = (int) (((float) byte_counter) / size) * 100);
21476160 * 100 = 2 147 616 000
大于2 147 483 647
,即最大整数。
你溢出了。
使用long
进行计算。
2^31-1 = 2147483647 < 21476160 * 100 = 2147616000
00000100 00110111 10000000,由于最高有效位是 1,因此它被解释为负数。