2011-05-18 79 views
2

我正在编写一个小小的下载管理器,当我尝试以百分比计算下载进度时,我得到一个有趣的输出。这是我用它来计算的话:两个int的乘法得到负数

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 
[...] 

我不知道为什么,但计算结果为负数。 由于正常的整数应该与数字一致,直到2 -1,这应该不是问题的根源。 但是我错过了什么?

+0

呃,相反,一个正常的整数应该罚款数字高达'2^31-1',或'2,147,483,647' – StriplingWarrior 2011-05-18 20:54:09

回答

7

http://en.wikipedia.org/wiki/Arithmetic_overflow

在Java解决,请尝试使用long代替。操作

int progress = (int) (((float) byte_counter)/size) * 100); 
+0

我试过了,问题是,第一次计算的结果'(byte_counter * 100 )'永远不会保存在任何变量中(应该只在内存中)。所以我不确定在哪里指定使用的数据类型。 – 2011-05-18 20:52:44

+1

@Lucas,上面的'100L'表示法指定一个'long'值为100.这将导致'byte_counter'在乘法发生之前被提升为'long'。一般来说,你可以通过执行'((long)byte_counter)'强制'byte_counter'被提升为'long'。 – 2011-05-18 20:54:05

+0

啊,thx指出了这一点!现在它工作正常。 – 2011-05-18 21:05:20

5

21476160 * 100 = 2 147 616 000

int progress = (int) ((byte_counter * 100L)/size); 

或反向次序比2 147 483 647,最大INT越大。

你满溢了。您可以使用long进行计算。

3
2^31-1 = 2147483647 < 21476160 * 100 = 2147616000 
2

你应该使用长 - 2147760000二进制是千万00000100 00110111 10000000且因为最显著位为1时它被解释为负数。