ID:278494
 
Lately I have been messing with the Java language and Net Beans. However, I encountered a strange happening that makes no sense to me...

If I am not mistaken, the following operation should yield 10.
public class whatever
{
int max = 1000;
int current = 100;
public static void main(String args[])
{
int percentage = current/max*100;
JOptionPane.showMessageDialog(rootPane,percentage);
}
}


Why does it yield 0? 100/1000 = 0.1 and then 0.1 * 100 = 10.
int is integer, it doesn't do decimals, you need to use float for decimal numbers IIRC, it's been ages since I did anything in java.
This expression would compile into code of the form:

temp = current / max;
percentage = temp * 100;

Since current is 100 and max is 1000, (and we're working with integers), current / max would come out as 0 (you can fit 1000 into 100, 0 times). Then, temp * 100 would be 0 * 100 = 0.

If you reversed the order of the multiplication and division i.e.

temp = current * 100;
percentage = temp / max;

You would get:
temp = 100 * 100 = 10000;
current = 10000 / 1000 = 10 (which is the answer you want).
In response to Hazman
However, that operation would not be universal...

400/800 = 0.5 -> 50%
800/400 = 2 -> 200%

But anyways... Even when I change the percentage variable to a double, I still end up with 0 (well... 0.0 but yeah).
In response to Spunky_Girl
You need to make max and current doubles before you divide them. Also, if you ever do any dividing by constants, make sure you include a decimal point (e.g. 2.0) so the compiler treats it as a double and not an integer.

That said, I would suggest using floats unless you truly need the precision of doubles:

float percentage = ((float)current/(float)max)*100.0f;

(The 'f' in 100.0f tells the compiler to treat it as a float, and not a double)
In response to Spunky_Girl
Spunky_Girl wrote:
However, that operation would not be universal...

400/800 = 0.5 -> 50%
800/400 = 2 -> 200%

I think you've misunderstood the transformation: I'm saying that (100 * x) / y == 100 * (x / y)

But anyways... Even when I change the percentage variable to a double, I still end up with 0 (well... 0.0 but yeah).

This is because Java is still treating the operands as integers: case them to floats or doubles and this will work:
public class whatever
{
int max = 1000;
int current = 100;
public static void main(String args[])
{
int percentage = (int)((double)current/(double)max*100);
JOptionPane.showMessageDialog(rootPane,percentage);
}
}
In response to DarkCampainger
As a matter of curiosity, why do you recommend doubles over floats here?
In response to Stephen001
I assume you meant 'floats over doubles.'

I'm guessing just because they use less memory. (32-bits instead of 64-bits.)
As I recall from my assembly course, the floating point data is converted to 80-bit floats internally before any processing is done on them anyways. (And then they're converted back to 32-bit or 64-bit afterwards.)
So, I don't think it's any more efficient.
Perhaps because of SSE operations, it would be better to store them in 32-bit, as well.
In response to Complex Robot
It's somewhat moot-point in this instance, though.

The matter of memory use does play a useful role in float arrays versus double arrays under Java, your double array will be twice the size of an equivalent float array, and for big arrays that will of course make a difference.

Ultimately the data storage mechanism used by the underlying VM (and it's respective CPU operations on that) are the choice of the VM. Whether SSE, SSE2, SSE3 etc etc comes into play is for the VM to decide and it's performance characteristics are VM specific, not true of the Java language in the main. This makes them an unreliable optimisation at best, and reliance on that behavour to be an anti-pattern.

This is actually remarkably true of C++ also, but we often forget it. The best example being the data width of long on LP64 platforms like Linux, compared to LLP64 platforms like Windows. Comparing -O0 and -O2 on GCC alone will demonstrate just how many ways the compiler can choose to implement your program logic.
In response to Stephen001
Agreed. If you're going with float because you think it's faster than double, you're probably wrong, and if it really matters you should be using fixed-point anyway. If you're going with float instead of double because of storage, then it's only relevant if you've got a lot of the buggers.
In response to Stephen001
Actually it was simply because that was what the OP was using.