Java: Variable assignment issue - java

just a quick question and I'm probably gonna feel stupid for asking but still would like to know why it is so...!
Anyways, quick example:
x is a double.
double conversion = (x-32)*5/9;
This does the maths just fine.
double conversion = (x-32)*(5/9);
This isn't fine because the (5/9) is being treated as an int, thus result is overall 0.
double conversion = (x-32)*(5f/9f);
This does the maths just fine, as it explicitly makes the 5/9 values a float.
So my question is: Why does the first equation work perfectly fine? ( double conversion = (x-32)*5/9; )
Why isn't the 5/9 being made a 0 if it were an int supposedly? What makes the 5/9 different from (5/9) ?

The difference is between whether you do the multiplication first or the division first - and what the types of those operations are.
This:
(x - 32) * 5 / 9
is equivalent to:
((x - 32) * 5) / 9
So if the type of x is double, then the type of x - 32 is double, so the 5 is promoted to double, the multiplication is done in double arithmetic, giving a double result, and then the division is also done in double arithmetic.
Even if x is an integer type, you're doing the multiplication first, which will presumably give you a value bigger than 9 (in your test case), leaving you with a non-zero result. For example, if x is 45, then x-32 is 13, (x - 32) * 5 is 65, and the overall result is 7, then converted to 7.0 on assignment. That's not the same result you'll get if x is a double with the value 45.0, but it's still better than multiplying by 0...

You basically answered your own question. Evaluation order makes all the difference.
basic left to right evaluation results in different type casting than your explicit evaluation order in your second example

Assuming x is a double then your first equation divides a double by an integer due to order of operations.
(x-32) = y-> y*5 = z -> z/9
at each stage a double is being operated on, overriding integer arithmetic.

It is the order it's done in.
If you multiply by 5, you get a large number. If you then divide by 9, you still get an int,
But the remainder is discarded.

The reason is the order of the operations.
(x-32)*5/9 makes first (x-32)*5 and then divides the result by 9
(x-32)*(5/9) makes first (x-32) and (5/9). After both results are multiplied.

Your value of x might be double and it is making entire equation in double because brackets execute first.

It's a matter of when the conversion takes place. 5/9 consists of one 5 and one 9 (both ints) being divided with integer division. If either is a float (5f/9 or 5/9f) they will divide as floats.

Related

Arithmetic in Java: Whats wrong with my equation? [duplicate]

This question already has answers here:
Int division: Why is the result of 1/3 == 0?
(19 answers)
Closed 4 years ago.
This is a basic question but I can't find an answer. I've looked into floating point arithmetic and a few other topics but nothing has seemed to address this. I'm sure I just have the wrong terminology.
Basically, I want to take two quantities - completed, and total - and divide them to come up with a percentage (of how much has been completed). The quantities are longs. Here's the setup:
long completed = 25000;
long total = 50000;
System.out.println(completed/total); // Prints 0
I've tried reassigning the result to a double - it prints 0.0. Where am I going wrong?
Incidentally, the next step is to multiply this result by 100, which I assume should be easy once this small hurdle is stepped over.
BTW not homework here just plain old numskull-ness (and maybe too much coding today).
Converting the output is too late; the calculation has already taken place in integer arithmetic. You need to convert the inputs to double:
System.out.println((double)completed/(double)total);
Note that you don't actually need to convert both of the inputs. So long as one of them is double, the other will be implicitly converted. But I prefer to do both, for symmetry.
You don't even need doubles for this. Just multiply by 100 first and then divide. Otherwise the result would be less than 1 and get truncated to zero, as you saw.
edit: or if overflow is likely, if it would overflow (ie the dividend is bigger than 922337203685477581), divide the divisor by 100 first.
In Java
Integer/Integer = Integer
Integer/Double = Double//Either of numerator or denominator must be floating point number
1/10 = 0
1.0/10 = 0.1
1/10.0 = 0.1
Just type cast either of them.
Convert both completed and total to double or at least cast them to double when doing the devision. I.e. cast the varaibles to double not just the result.
Fair warning, there is a floating point precision problem when working with float and double.
If you don't explicitly cast one of the two values to a float before doing the division then an integer division will be used (so that's why you get 0). You just need one of the two operands to be a floating point value, so that the normal division is used (and other integer value is automatically turned into a float).
Just try with
float completed = 50000.0f;
and it will be fine.
As explain by the JLS, integer operation are quite simple.
If an integer operator other than a shift operator has at least one operand of type long, then the operation is carried out using 64-bit precision, and the result of the numerical operator is of type long. If the other operand is not long, it is first widened (§5.1.5) to type long by numeric promotion (§5.6).
Otherwise, the operation is carried out using 32-bit precision, and the result of the numerical operator is of type int. If either operand is not an int, it is first widened to type int by numeric promotion.
So to make it short, an operation would always result in a int at the only exception that there is a long value in it.
int = int + int
long = int + long
int = short + short
Note that the priority of the operator is important, so if you have
long = int * int + long
the int * int operation would result in an int, it would be promote into a long during the operation int + long
As your output results a double you should cast either completed variable or total variable or both to double while dividing.
So, the correct implmentation will be:
System.out.println((double)completed/total);

java 2 different formula problems

I want to calculate the volume of a sphere using a Java program. So, I used
double result = 4/3*Math.PI*Math.pow(r,3);
This formula gives the wrong answers it seems.
Like Java program opt 4/3, but if I change it to
double result= Math.PI*Math.pow(r,3)*4/3;
it gives me the correct answer. Does any one know what is going on?
This has to do with the order in which casting occurs in Java (or C for that matter).
For the full details on operator precedence, see http://introcs.cs.princeton.edu/java/11precedence/.
In your first case, since the multiply and divide operators are computed from left to right, the first operation java interprets is 4/3. Since both operands are integer, java computes an integer division, the result of which is 1.
In your second case, the first operation is the double multiply: (Math.PIMath.pow(r,3)). The second operation multiplies a double (Math.PIMath.pow(r,3)) by an integer (4). This is performed by casting 4 to a double and performing a double multiply. Last, java has to divide a double (Math.PI*Math.pow(r,3)*4) by an integer (3), which java performs as a double division after casting 3 to a double. This gives you the result you expect.
If you want to correct your first answer, cast 3 to double first:
4/ (double)3
and you will get the result you expect.
The difference in the outcome is due to operator precedence. In Java, multiplication and division have equal precedence, and therefore are evaluated from left to right.
So, your first example is equivalent to
double result = (4/3)*Math.PI*Math.pow(r,3);
Here, 4/3 is a division of two integers, and in Java, in such cases integer division is performed, with outcome 1. To solve this, you have to explicitly make sure that one or both of the operands is a double:
double result = (4.0/3.0)*Math.PI*Math.pow(r,3);
Your second example, however, is equivalent to
double result = (Math.PI*Math.pow(r,3)*4)/3;
Here, the Math.PI*Math.pow(r,3)*4 part is evaluated to a double, and thus we have no integer division anymore and you get the correct result.
4/3 is a division between two int, so Java assumes that the result is also an int (in this case, this results in the value 1). Change it to 4.0/3.0 and you'll be fine, because 4.0 and 3.0 are interpreted as double by Java.
double result = 4.0 / 3.0 * Math.PI * Math.pow(r,3);

Cast problems between int and double [duplicate]

This question already has answers here:
math.random, only generating a 0?
(4 answers)
Closed 8 years ago.
This piece of code is giving the result I wanted
double a=Math.random()*100;
int b=(int)a;
System.out.println(b);
but when I did for the same thing this way, it is giving zero always
int a=(int)Math.random()*100;
System.out.println(a);
As far as I know typecasting will store the bigger data-type to small. but in the later code, I'm gettig zero every single time I run the program.
(int)Math.random()*100; means:
cast the value of 'Math.random()' to int and then multiple by 100. Since Math.random returns a number between 0 and 1 casting to int will always chop off the decimal path and give you 0.
The correct way to do it is
(int)(Math.random()*100);
Try with,
int a=(int)(Math.random()*100);
System.out.println(a);
Math.random() Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0. Returned values are chosen pseudorandomly with (approximately) uniform distribution from that range.
Type casting is both right-to-left associative, and has a higher precedence than multiplication.
Source
Let me break it down a bit.
Like any other operator, a type cast has a certain level of priority attached to it. Certain operators have higher priority than others, and certain operators associate with their arguments in a certain way. For example, numerical operations are typically left-to-right associative; that is, with operators of an equal priority, one can parenthesize them from the left and get the same result.
Example:
5 * 5 * 5 / 3 + 5 -> (((5) * 5) * 5) / 3) + 5
Right-to-left associativity would allow you to parenthsize the operations from the right to achieve the same result.
Example:
int x;
int y;
int z;
x = y = z = 10 -> x = (y = (z = (10))
Type casting, much like assignment, is right-to-left associative, so it's going to essentially use the rightmost argument to satisfy its closest association, then progress backwards through the chain until you reach the ultimate goal.
This means that you could write this as valid syntax, although it would be very strange:
Object foo = (Object)(Number)(float)Math.random();
First, we cast our result from a double to a float, then to a Number, then to an Object (which is totally redundant, but possible).
The priority bit in particular is what causes the multiplication to apply last in this chain of events.
Bear in mind, in no one level of priority does the language intermingle associativity. That means an operator at level 1 priority associates in a specific way, and operators in level 2 operate in a specific way.
So, we come now to your expression:
int a = (int) Math.random() * 100;
Casting has a priority level of 3. The mathematical operator * has a priority level of 4. So, Java sees your statement like this:
int a = ((int) Math.random()) * 100;
The parentheses are there for extra clarity. (Note that parentheses have the highest priority.)
What you want to do, as explained more tersely in other answers, is use the parentheses to force your intended priority instead of letting Java decide. So, you would write this instead:
int a = (int) (Math.random() * 100);
This forces Java to evaluate the multiplication before the cast, since the parentheses have a higher priority than the cast.
Because the cast to int happens before the multiplication and as Math.random() generates a number between 0 (inclusive) and 1 (exclusive), it is rounded to 0.
You are casting before multiplying here...
Math.random() will generate number between 0 and 1 and will be rounded to 0 before multiplying with 100.
(int)(Math.random()*100) will behave as you want.
Consider using java.util.Random:
Random random = new Random();
int value = random.nextInt(100);
System.out.println(value);
Random is thread-safe, whereas Math.Random() is not.
When testing, you can feed a Random the same seed to generate reproducible pseudorandom numbers. You can't with Math.Random().
and more.
See more here: Math.random() versus Random.nextInt(int)
use this :
int a=(int)(Math.random()*100);
System.out.println(a);

Java: Is (int) double reliable?

When I perform simple math in java with doubles and other number data types, the double values seem to randomly vary a bit from the supposed result, which might be 5,59999999997 or 6,0000000002 or something. When I cast to int, the double value is obviously rounded down to the next whole number. Does this mean the double could be both 5 or 6? Or does that "5,999999999997" still count as 6 though which would be depending on the binary float value? If not, is there a way to let the negative vary be rounded up, but not lower values from 5,5 to 5,999999999996?
I mean, I dont really want to round the value as described in my last sentence. I'd like to always round down to the next whole number, but I don't want to cause an extra decrement due to wrong double math results.
Converting a double to an int always rounds down. You can round to the nearest whole integer via Math.round(double). The double is varying from what you expect because of floating point error.
If you want to round, you can use the round() method.
double d = 6 +/- some small error
long l = Math.round(d);
Or you can add 0.5 for positive numbers
long l = (long) (d + 0.5);
or
long l = (long) (d + (d < 0 ? -0.5 : 0.5));
I'm not sure I understand the question. Usually when you cast a double to int you add 0.5 to have a nice round.
From the Java Language Specification:
The Java programming language uses round toward zero when converting a floating value to an
integer (§5.1.3), which acts, in this case, as though the number were truncated, discarding
the mantissa bits. Rounding toward zero chooses at its result the format's value closest to
and no greater in magnitude than the infinitely precise result.
So 5,999999999997 when casted to an int will 5 and 6,0000000002 will be 6. If I understand what you are asking with having negative versions of the values (e.g. -5.97), I fail to see how
Math.round() does not suffice you. -6,0000000002 will be rounded to -6 as will -5,999999999997 and every other value above (but not including) -5.5.

Not sure why programme returns an int

Ok so basic question here.
double test = 1/3 * 3.14;
I realize that you need to do (1.0/3) in order to get the actual double number. But what I am wondering is why. I would have thought that since you are multiplying by 3.14 this would make it a double.
So am I correct in thinking that whenever two values are used in an arithmetic equation, regardless of what is happening around them, if they are integers then you will get an integer value?
ie. x/y * z
while x is divided by y that is all that the programme cares about and if they are both integers you will get an integer value back? It is only when you multiply it by z (3.14) that it becomes a double.
Evaluation occurs from left to right when two operators have equal precedence. * and / have equal precedence.
1 / 3 * 3.14 evaluates 1 / 3 first. Both operands are int, the first operation is integer division, and the result is an int.
Next, result * 3.14 is evaluated. One operand is an int, the other operand is a double, and we have mixed types. Java does us a favor and casts the int to a double to preserve accuracy. Floating point division occurs, and the result is a double.
With operators of equal precedence, the associativity takes over. These operators / and * are left-associative, which means that the order of operations proceeds from left to right.
So, 1/3 happens first, and integer division happens before the 3.14 has a chance to promote them to doubles.
Because according to the rules of arithmetics, 1/3 is calculated first. Since it's 2 integers, it's an integer division, resulting in 0. Afterwards you have a double calculation, but the error has already happened.
My understanding is that this has to do with autoboxing in java. Java assumed that the 1/3 is dividing two ints so you'd get an int back (casted into a double).
If you did 1/3D, you'd get 0.33333333 back

Categories