Multiplication of two int's gets negative - java

I'm currently coding a little download manager and I get a funny output when I try to calculate the download-progress in percent. This is what i use to calculate it:
int progress = (byte_counter * 100) / size;
System.out.println("("+byte_counter+" * 100) = "+(byte_counter * 100)
+" / "+size+" = "+progress);
byte-counter is an int (it counts the total bytes read from the InputStream) and size is the length of the downloaded file in bytes.
This works great with small downloads. But when i get to bigger files (40MB) it starts making funny things. The Output for the calculation looks like this:
[...]
(21473280 * 100) = 2147328000 / 47659008 = 45
(21474720 * 100) = 2147472000 / 47659008 = 45
(21476160 * 100) = -2147351296 / 47659008 = -45
(21477600 * 100) = -2147207296 / 47659008 = -45
[...]
I don't know why, but the calculation gets negative. Since an normal Integer should be fine with numbers till 231-1, this shouldn't be the problems root. But what am I missing?

See http://en.wikipedia.org/wiki/Arithmetic_overflow
To fix in java, try using a long instead.
int progress = (int) ((byte_counter * 100L) / size);
or reverse order of operations
int progress = (int) (((float) byte_counter) / size) * 100);

21476160 * 100 = 2 147 616 000 is greater than 2 147 483 647, the max int.
You're overflowing.
Use long for your calculations.

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

You should use a long -- 2147760000 in binary is 10000000 00000100 00110111 10000000 and since the most significant bit is 1 it is interpreted as a negative number.

Related

Rounding a number to 10^ form JAVA

I have a random number such as 35 127 3658 45782 etc... I want to round them to 10^ form like 10 100 1000 10000. I can do it with this code:
Math.pow(10, (int)(Math.log10(number)) + 1);
But this code seems to me a bit complex and long for basic operation like that. Is there a better way to do it?
float t =10,number;
//scan a value for "number"
while(number/t > 1)
{
t = t * 10;
}
if( (number/t) % 1 >= 0.5)
System.out.println(t);
else
System.out.println(t/10);
Though it takes more lines, this is simple to understand.

Java BigInteger factorization: division and multiplication differ

I'm writing a code to factorize a big number (more than 30 digit) in Java.
The number (n) is this: 8705702225074732811211966512111
The code seems to work and the results are:
7
2777
14742873817
By logic the last item should be obtainable by doing (n/(fact1 * fact2 * fact3)) and it results:
30377199961175839
I was very happy with this, but then decided to take a little test: I multiplied all the factor expecting to find n... But I didn't!
Here is my check code:
BigInteger n = new BigInteger("8705702225074732811211966512111");
BigInteger temp1 = new BigInteger("7");
BigInteger temp2 = new BigInteger("2777");
BigInteger temp3 = new BigInteger("14742873817");
BigInteger temp4 = n.divide(temp1).divide(temp2).divide(temp3);
System.out.println(n.mod(temp1));
System.out.println(n.mod(temp2));
System.out.println(n.mod(temp3));
System.out.println(n.mod(temp4));
System.out.println(n.divide(temp1).divide(temp2).divide(temp3).divide(temp4));
System.out.println(temp1.multiply(temp2).multiply(temp3).multiply(temp4));
System.out.println(n);
As you can see I simply define the number n and the factors (the last one is defined as n/(fact1 * fact2 * fact3) then check that n/eachfactor gives remainder 0.
Then I check that ((((N / (fact1)) / fact2) / fact3) / fact4) = 1
Lastly I check that fact1 * fact2 * fact3 * fact4 = n
The problems are:
n mod temp4 is not 0, but 245645763538854
fact1 * fact2 * fact3 * fact4 is different from n
but ((((N / fact1) / fact2) / fact3) / fact4) = 1
Here is the exact output:
0
0
0
245645763538854
1
8705702225074732565566202973257
8705702225074732811211966512111
This has no sense... How can the fourth factor be wrong and right at the same time?
I'm sorry to report :
8705702225074732811211966512111/(7*2777*14742873817) =
30377199961175839.8571428571
Where it should be a whole number.
So, your factorisation is wrong ... oops ..
Try bc under linux, for windows : http://gnuwin32.sourceforge.net/packages/bc.htm.
It can deal with these kind of numbers
this page says the actual factorization of your BigInteger is 7*2777*2106124831*212640399728230879
System.out.println(temp3.mod(temp1));
The above code gives 0, which means temp3 is not prime. temp4 is not a factor.

Same Calculation, different result?

My goal is to calculate how many percent counter out of cap is.
Now I ran over a problem, I can't find the difference between the two formulas below, as far as my mathematical understanding tells me, it's exactly the same calculation. But only the first one works, brackets make no difference.
int i = counter * 100 / cap; //works
int i = counter / cap * 100; //doesn't work
Has this got something to do with java or is it just me who's made a horrible thinking mistake?
It is not the same calculation, since you are handling integer arithmetics, which does not have Multiplicative inverse number for all numbers (only 1 has it).
In integer arithmetics, for example, 1/2 == 0, and not 0.5 - as it is in real numbers arithmetics. This will of course cause later on inconsistency when multiplying.
As already mentioned - the root of this is the fact that integer arithmetics does not behave like real numbers arithmetics, and in particular, the divide operator is not defined as a/b == a*b^-1, since b^-1 is not even defined in integer arithmetics to all numbers but 1.
Your mistake is assuming that these are just pure, abstract numbers. I assume that counter is an int... so the second version is evaluated as:
int tmp = counter / cap;
int i = tmp * 100;
Now we're dealing with integer arithmetic here - so if counter is in the range [-99, 99] for example, tmp will be 0.
Note that even your first version may not work, either - if counter is very large, multiplying it by 100 may overflow the bounds of int, leading to a negative result. Still, that's probably your best approach if counter is expected to be in a more reasonable range.
Even with floating point arithmetic, you still don't get the behaviour of "pure" numbers, of course - there are still limits both in terms of range and precision.
First case
int i = counter * 100 / cap;
is evaluated like
(counter * 100) / cap;
The second case
int i = counter / cap * 100;
is evluated like this
(counter / cap) * 100
Hence different results
In Java, operators * and / have the same precedence, so the expressions are evaluated sequentially. I.e.
counter * 100 / cap --> (counter * 100) / cap
counter / cap * 100 --> (counter / cap) * 100
So for values e.g. counter = 5, cap = 25 (expecting count and cap to be both int variables), the evaluation is in the first case: 5 * 100 = 500, then 500 / 25 = 20
In the second case, the evaluation is: 5 / 25 = 0 (integer math!), then 0 * 100 = 0.

value to the next thousand instead of nearest thousand

Sorry im new to java, currently i wanted to code the value to next thousand instead of nearest thousand. But i have no ideas how to do it. I tried Math.round but it's for roundest. Please guide me, any help would be appreciated .
Expected output that i looking for :
example 1) if the place values less than 999, it will direct change to 1000
May i know how can i code the math formula for this ?
You can use Math.ceil for this.
// A quick code example :)
int val = 1400;
val = (int) (Math.ceil(val / 1000.0) * 1000);
You need to write some custom code as follow
int leftdigit=value/1000;
int nextthousand=(leftdigit+1)*1000;
Here Kindly note Math.ceil returns double so you should use it properly as stated below as for integer value it won't work properly and integer division will be performed.
double data = 1100;
data = Math.ceil(data / 1000) * 1000;
System.out.println(data);
OUTPUT
2000.0
Conversion from integers to floats leads to chaos, as for the same bit size, float mantissa length will always be smaller than integer size (IEEE-754 float mantissa is 23 bits vs 31 bits for the integer). Converting a large integer to float back and forth will not give the same integer after the conversion.
So here using Math.ceil() may work for integers or small long ints, but will break for large long values (63 bits).
Better use the following code (only works for value > 0):
int ii = ((i - 1) / 1000 + 1) * 1000;
or for long int version:
long ii = ((i - 1) / 1000 + 1) * 1000;
Does not unnecessarily overflow, keep precision even for large values, and probably way faster!
Addenda
As an example, the following java code:
int largeint = Integer.MAX_VALUE - 63;
float fl = (float)largeint;
int largeint2 = (int)fl;
System.out.println(largeint);
System.out.println(largeint2);
Print:
2147483584
2147483647

Trouble printing the value of a Long division and multiplication

I have trouble figuring out why a simple division like this one always returns 0.
System.out.println(4091365376L / 4091495462L * 100L);
I suffixed all numbers with Ls so they're treated as Longs. I keep getting a zero.
I'm trying to calculate the percentage of 4091365376L to 4091495462L. My values are Longs but I'm just looking for a simple Integer value.
You are a victim of integer rounding (actually: truncation). Try this:
System.out.println(4091365376L * 100L / 4091495462L);
Prints 99. Or cast to double implicitly:
System.out.println(100.0 * 4091365376L / 4091495462L);
Giving 99.99682057572328. Your problem is that 4091495462L is slightly bigger than 4091365376L so when diving them, the result is truncated to 0 (try 3 / 4, if you are not convinced). and 0 times 100 is...
4091365376L / 4091495462L * 100L
\_______________________/ |
0.99... = 0 |
\_________________________/
0
You could express it like
100 * 4091365376L / 4091495462L
then it would become
100 * 4091365376L / 4091495462L
\_______________/ |
409136537600L |
\____________________________/
99.99... = 99
Order is important, as is type. The output of a long divided by a long is a long. The result of the division you're performing is 0, and 0 * 100 == 0. You would be much better off using something like this:
System.out.println((long) (4091365376.0 / 4091495462.0 * 100));
In integer math:
4091365376 / 4091495462 = 0
0 * 100 = 0
You're expecting
4091365376 / 4091495462 = 0.9999682057572327
0.9999682057572327 * 100 = 99.99682057572327
but you can't do that with integers (or long integers). Use doubles if you want a double value.

Categories