Parentheses and order of operations - java

I have a function in java that returns an integer. I know what it is supposed to return so I know when it runs correctly or not. Anyway, there is this line of code at some point in a for loop:
If I write it like this
miuf = miuf_ant * nf_ant / nf - ((double) ((t - 1) * hist[t - 1]) / (double) nf);`
the result is fine.
If I write it like this
miuf = (miuf_ant * (nf_ant / nf) - ((double) ((t - 1) * hist[t - 1]) / (double) nf));
the result is way off.
nf_ant, nf and t are ints, the rest are doubles.
I have evaluated these 2 expressions in the debugger for a few iterations and the results differ by some 0.3 in general. Why does this happen and why is it that one works and the other doesn't?

If nf_ant and nf are ints, your problem is that the second version if performing integer division and not floating point division. You need to cast one of them first.
Let's compare the following two expressions:
miuf_ant * nf_ant / nf
miuf_ant * (nf_ant / nf)
The first one is equivalent to the following by the rules of Java:
(miuf_ant * nf_ant) / nf
What happens here is that the product is evaluated first, and because miuf_ant is double, the result is also a double. Afterwards, the same happends for the division.
In the "bad" (second) case though, because both division operators are ints, the result is also an int, losing precission on the operation by effectively truncating the result. This loss of precission is then carried to the product.

In the second case, nf_ant / nf will be computed in integer arithmetic as the parentheses mean it's evaluated on its own. This loss of the remainder is the cause of the difference.
In the first case it is premultiplied by miuf_ant which is a floating point type. Since * and / have the same precedence, all 3 arguments are promoted to floating point prior to computation.

Related

What does -1+ (int) mean?

I have a line of code in java, but I don't know how to explain how it works, someone knows what the -1+ (int) means
-1+ (int) ((Math.random () * (3)));
The (int) actually goes with the next portion of code: it casts the result of ((Math.random () * (3))) to an integer. (This will simply drop the decimal portion; it will not round).
Math.random() returns a number that is greater than or equal to 0.0 and less than 1.0.
((Math.random () * (3))) simply returns a double that is greater than or equal to 0.0 and less than 3.0, which will, as I just mentioned, subsequently be cast to an int. (This will result in a number between 0 and 2; 3 isn't possible).
Adding -1 to something is equivalent to subtracting 1.
So, this will result in a random integer between -1 and 1 (inclusive).
someone knows what the -1+ (int) means
This is the wrong way to look at it. Instead, you should break it down this way:
The + is adding two things together. On the left we have -1 a literal integer. On the right we have (int) ((Math.random () * (3))). Now we can break down what's in the parentheses. First we multiple two values, the result of Math.random() and the value (3). The result is a floating point number and the (int)` casts it to an integer.
What does -1+ (int) mean?
You are having problems understanding this is because you haven't grasped Java precedence rules and (apparently) what a type-cast looks like.
Lets start with this part:
((Math.random () * (3)))
That means:
call the Math.random() method
multiply the result by 3.
Note that there some extra parentheses here that aren't necessary. We could just write it as:
(Math.random() * 3)
Now lets look at the original expression:
-1 + (int) ((Math.random() * (3)));
In the above (int) means type-cast. Cast the type of the "following" to the type in the parentheses. In this case, it says
"cast the random number multiplied by 3 to an int". That will perform a primitive conversion of that value to int.
Next, the -1 means the number "minus one", and the + means addition. So the whole thing means
Add -1 to a random number multiplied by 3 and converted to an integer.
What is the conversion actually there for?
Well Math.random() actually produces a double value between 0.0 (inclusive) and 1.0 (exclusive). And multiplying that by 3 gives another double value. So the (int) cast is converting the double to an int.
Which tells us the complete meaning of that expression:
Generate a random integer in the range -1 to +1.
I mentioned the precedence rules. These are the rules that (in effect tell you what the subexpressions are. For example
a * b + c
means
(a * b) + c
because * has higher precedence than +.
So in our example we have the following operators:
The - in -1 is a unary minus (negation)
The + is binary plus (addition)
The (int) is a type cast
The Math.random() is a method call
The * is a binary multiplication
The ( ... ) are parentheses.
The order of precedence for these operators is
parentheses highest
method call
negation
type cast
multiplication
addition
So you can see that we needed the outside parentheses in (Math.random() * 3) so that the type cast applies to the product rather than (just) result of the method call.
Here is a table showing the precedence of all operators (and similar) in Java 11:
Operator precedence in Java

Why does (int)(2/0.9) = 2?

I put this into java and I was given the result 2. Was wondering why it isn't an ArithmeticException, as shouldn't (int)(2/0.9) turn into 2/0. All help is appreciated.
Your code is
(int) (2 / 0.9)
So the int-cast is only applied to the result after computing 2 / 0.9. Now 2 / 0.9 divides an int by a double value. In such a case the int will also be interpreted as double (2.0 in this case). The result is thus like
2.0 / 0.9 = 2.22...
This process is known as numeric promotion (it uses widening primitive conversion here JLS§5.1.2). From JLS§5.6:
A numeric promotion is a process by which, given an arithmetic operator and its argument expressions, the arguments are converted to an inferred target type T. T is chosen during promotion such that each argument expression can be converted to T and the arithmetic operation is defined for values of type T.
After that you cast to int which will round the value to the next lower integer, 2 in this case. Thus the result is 2.
What you expected would be the result of an expression like
2 / (int) 0.9
// or more explicit:
2 / ((int) 0.9)
which first casts the 0.9 to an int before dividing. In this case you would correctly get
2 / 0
yielding the expected ArithmeticException.

How To Solve Mathematical Expression In Java?

I am trying to get percentage but the result is error, i have expression as:
Uper=(Upcount/total)*100;
where Uper is float while Upcount and total is integer i am getting the result Uper=0.
An int divided by an int will result in an int. That could be 0. Multiply 0 * 100, convert to float, and the result is still 0.0. You need at least one of the operands to be floating point before the division will give a floating point result.
Try:
Uper = ((float)Upcount/(float)total)*100.0;
The extra (float) is me being paranoid that this line might be modified in the future without fully understanding the floating-point requirement. The 100.0 is to be explicit about what you want -- a floating point result.
Perhaps changing Upcount or total to float would make more sense.
the division of 2 integers will always result in an integer which is 0 in your case.
To solve this, use the following code:
Uper = ((Double) Upcount) / total * 100
Casting at least 1 member to Double or Float will get the result you want

How to calculate integer expression in Java

Suppose, I need to calculate 3 * (2 / 3) = 2 but 3 * (2 / 3) = 0 in integer arithmetic. So, it looks like I should use floating-point arithmetic 3 * (2.0 / 3) = 2.0 and cast the floating point result to int.
Does it make sense? How would you avoid casting here?
In this particular example, you may be better off rearranging the expression as 3 * 2 / 3, or as 3 / 3 * 2. This way you'll get the exact result using integer math alone.
Using floating-point math is the more general solution, but you need to be aware of rounding issues. In general, you shouldn't expect that x * (y / x) would give you exactly y when x and y are floating-point numbers.
If you know that the result is an integer, or simply want to round it to the nearest integer, you could use Math.round():
Math.round(3 * (2f / 3))
Simply casting the result to int is not a good idea since floating-point numbers are inexact, and such a cast would simply truncate the number.
You can't avoid casting. You can either use integer division or you can use full division but then arguments and result will be in floating point.
You can try moving around the expression parts to bring out the integer division to the top level. In your case you could transform 3 * (2 / 3) to (3 * 2) / 3 which will result in 2 without any floating point operations.
* and / have the same precedence, so omitting the parentheses will provide you with a correct result of the example.
Casting (or truncating) is unavoidable otherwise.
Personally I would re-arrange the equation to be:
3 / 3 * 2 = 2
But not sure if thats what you need. You could try doing the calculation on float's and then use round() to round it up or down to the nearest integar.
This is because of the integer division. In these kinds of expressions you are better off using float, yes.
You can avoid the explicit casting only if you are using the compound operator. The compound operator does an automatic cast for you.
int a = 3;
a *= (2.0/3);
System.out.println(a);
What exactly is it you want to achieve? Using integer arithmetic the result depends on where you set you parentheses. (a/b) * (c/d) * (e/f) will, as you noticed yourself, in general result in something different than (a*c*d) / (b*d*f), even though mathematically both expressions are equal. Nontheless both expressions may be correct depending on the task you want to solve. I do miss a clear statement of this.
If you are looking for the integer closest to the mathematically correct value just calculate nominator and denominator seperately and then perform the division. This way intermediate errors do not occur. If not you need to reformulate your question.

Applying casts to the results of integer and floating point division: what's going on here?

I'm a beginner and there's something that's not making much sense to me. Please could be so kind as to explain where I'm going wrong. I'm sorry if this has been asked before.
Here the presence of the decimal point mean these get evaluated using floating point division.
System.out.println(1/3.0); // this prints: 0.3333333333333333
System.out.println(1.0/3); // this prints: 0.3333333333333333
System.out.println(1.0/3.0); // this prints: 0.3333333333333333
Apparently, this below is an example of "truncating-integer division." It seems a bit weird to me but ok.
System.out.println(1/3); // this prints: 0
Is it ok to say: "in the line below, the (double) cast is evaluated 1st. It effectively says: "treat 1/3 as a double - don't use truncating integer division. instead use floating point division.""
System.out.println((double)1/3); // this prints: 0.3333333333333333
Below, however we get 0.0 - how did that happen?
System.out.println((double)(1/3)); // this prints: 0.0
ok so maybe the extra parentheses mean the (1/3) gets evaluated 1st. It is evaluated using truncating integer division yielding 0. And then the double is applied giving us 0.0 Ok that makes sense
Ok so we maybe can propose a couple of general rules here:
Rule 1: (double) expression means apply the (double) cast first then evaluate the expression.
Rule 2: (double) (expression) means evaluate the expression then apply the cast.
Great!
So in the next line below we have: (int) expression, so I guess we can apply rule 1). The (int) cast is evaluated 1st. It effectively says: "treat 1.0/3 as a int - don't use as much memory as you would with a double. Don't use floating point division, instead apply truncating integer division."" So we have 0 right? No.
System.out.println((int)1/3.0); // this prints: 0.3333333333333333
Ok so we have 0.33333 so the (int) cast is not evaluated 1st. It is as if it wasn't there. Let's propose a 3rd rule:
Rule 3: (int) expression means ignore the (int) cast altogether just evaluate the expression like the (int) isn't even there.
Ok applying rule 3 to the line below, we have (int) but we are just going to ignore it. 1.0/3.0 is evaluated with floating point division and we get 0.3333333. Success!
System.out.println((int)1.0/3.0); // this prints: 0.3333333333333333
And in the last line below, again we have (int) but we are just going to ignore it. (1.0/3) is evaluated using floating point division yielding 0.3333333333 right? No.
System.out.println((int)(1.0/3)); // this prints: 0
Ok now I'm confused. Please could you help me get my head round this?
Java's language parsing rules are basically implying a lot of parentheses everywhere in your code based on its rules of order of operations. Understanding where Java thinks the parentheses are will help you understand this behavior. When you say:
(double) 1 / 3.0
... this is equivalent to saying:
((double) 1) / 3.0
This means that 1 gets converted to a double, and 3.0 is automatically a double, so you'll end up doing a floating point division rather than integer division. The same thing would happen with (double) 1 / 3, because the divisor is a double, so even though the dividend is an int, the system realizes that you want to do floating-point division. The compiler doesn't want you to lose precision unless you specifically ask to, so any time either the dividend or the divisor is a double, it will do double division.
On the other hand:
(int) 1 / 3.0
... is the same as saying:
((int) 1) / 3.0
In this case, you're telling the compiler what it already knew: that the divisor (1) is an int. Then you're asking it to divide by a double value (3.0). Since the dividend is a double, it will perform double division.
As you noted, 1/3 will produce zero, because that's how integer division works and both numbers are integers. The same will happen with 1/(int)3.0 because you're telling the compiler to make the 3.0 into an int before the division will occur (as in 1/((int)3.0)).
The final point to keep in mind is that (int) 0.33 will also get converted to 0, because an integer can't hold decimal values in it. So when you say (int)(1.0/3), you're doing double division, but then you're converting the double into an int afterwards, producing 0.
This is specified in the Java Language Specification - Numeric Promotions
If any of the operands is of a reference type, unboxing conversion (§5.1.8) is performed.
Then:
If either operand is of type double, the other is converted to double.
Otherwise, if either operand is of type float, the other is converted to float.
Otherwise, if either operand is of type long, the other is converted to long.
Otherwise, both operands are converted to type int.
The concept is called widening conversion:
5.1.2 Widening Primitive Conversion
The following 19 specific conversions on primitive types are called the widening primitive conversions:
byte to short, int, long, float, or double
short to int, long, float, or double
char to int, long, float, or double
int to long, float, or double
long to float or double
float to double
The reason why
(int) (1.0/3) == 0
is because you cast the result of 1.0/3 (0.33333... by the above rules) explicitly to an integer, which is equivalent to "floor(result)" (rounding down), so the result is 0.
Cast has a higher precedence than /, that's why the other operations were misleading to your understanding:
(double) 1 / 3
will explicitly cast 1 to a double value 1.0 first, so again the result by the above rules is equal to 0.3333....
The cast is only applied to the expression immediately after it.
Examples:
(int)1/3
applies the cast to the 1. equivalent to ((int)1)/3
(int)(1/3)
the cast is applied to the result of the expression.
(int)((double)1.333*(float)3.167)
getting a little more complicated. 1.333 casted to double,
multiplied by 3.167 casted to a float, with the result casted to an int
Hope that helps!
There are two factors in all those cases:
Operator precedence
When one of the arguments of the division is a floating point number, the result is a floating point number.
I'll give three examples from your question:
(double) (1/3) - first evaluate the expression in parenthesis - (1/3) is an integer division so the result is 0, then cast it to double, you get 0.0
(int) (1.0/3) - first evaluate the expression in parenthesis - (1.0/3) is a floating point division, so the result is 0.3333, then cast it to int, and you get 0
(double) 1/3 - first perform casting so (double)1 becomes 1.0, then evaluate the division 1.0/3 - this is a floating point division, so the result is 0.3333

Categories

Resources