Why precision lost for double casting in Java? - java

I am surprised to see below difference in Java:
(double)(int1/int2) // return 0.0 - precision lost.
(double)int1/int2 // return 9.3123325E-10 - precision kept.
Is it by design that the bracket in the first expression makes the evaluation lose the precision?

Yes, it's by design. By putting the expression in parens, you're modifying the normal precedence, so int1/int2 will execute first, and because both are (presumably) integers, use integer division, which will truncate the result to an integer. In the second case, the normal precedence applies, so int1 is being converted to a double first, then the division done using floating point division.

It's a matter of order-of-operations. Parentheses have a higher priority than casts, so your first statement will perform the operations in the parentheses first - it casts the quotient to a double.
Casts have a higher priority than division, so in your second statement, the cast is applied before the division operation.

Because of the brackets (double)(int1/int2) first performs integer division (precision lose included) and then casts the result to double.
The (double)int1/int2 performs a double division because the first operand is double.

Absolutely. In statement 1 you do the division and then cast. In statement 2 you first cast int1 to a double, then you do division which promotes int2 to a double and precision is kept.
I don't intend this to sound snarky, but the language (and compiler) is doing what you asked it to do. :)

In the first one, you're doing integer division, then casting to double. Since integer division truncates any decimals, you're losing the decimal bit of the answer, and casting it to double doesn't bring that info back.
In the second, you're casting the top one to double, then doing double division. This makes the answer automatically a double, since it takes the higher-precision unit when dividing, and ensures that you're getting the decimal bit too.
The second is equivalent to ((double) int1) / int2, since casts have higher precedence than /.

I believe this has to do with the fact that parenthesis (per PEMDAS) causes the calculation to happen within the parenthesis before the cast occurs and as such, the decimal value if the division is less than 1 is 0.
Example:
(double) (3/5) = (double) 0; (Since Int can't be .6)
But (double) 3/5 --> (double) .6

Related

How to calculate angles based on sides in triangles [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);

New to Java. Inquiry on math operators on homework assignment [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);

Difference between (float)m/f and (float)(m/f)

int m = 10;
int f = 3;
float r = (float)m/f; // gives 3.333333 as output
float r = (float)(m/f); // gives 3.0 as output
Can anyone tell me how the parentheses are changing the answer because I am basically typecasting the integer value of m/f into float. What I don't understand is how the addition of brackets around m/f is changing the answer.
In the second case:
(float)(m/f)
you are doing integer division first and then casting to float and therefore you lose the fraction. In the first case you cast m to float and therefore end up performing floating point division.
The cast operator has higher precedence in both C++ and Java but using parenthesis around the division forces it to be evaluated first.
In C++ his behavior is due to the usual arithmetic conversions which is covered in the draft C++ standard section 5 Expressions paragraph 10 which says:
Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield
result types in a similar way. The purpose is to yield a common type, which is also the type of the result.
This pattern is called the usual arithmetic conversions, which are defined as follows:
and includes the following bullet:
— Otherwise, if either operand is float, the other shall be converted to float.
In Java this behavior is covered in the JLS section 5.6.2. Binary Numeric Promotion which says:
When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order:
and includes:
Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:
and includes:
Otherwise, if either operand is of type float, the other is converted to float.
and includes the following example:
int i = 0;
float f = 1.0f;
// First int*float is promoted to float*float, then
The difference is what gets converted to float. In the first case m gets converted to float, so the entire expression becomes floating point. In the second, you perform the expression (integer division) and then convert to float, at which point it's too late to save those precious significant digits.
(float)m/f divides (float)m by f. Since one of the operands is a float, the operator is floating-point division, and the answer is 3.333 etc.
(float)(m/f) calculates (m/f) and casts it to float. Since both operands are integer, the operation is integer division, and m/f is 3. Then 3 is casted to float to become 3.0.
On the first example, m gets casted to float first then divided which gives you a floating-point number. The second example, the division is an int division so it will give you an int number that then gets transformed to a floating-point number.
Adding parentheses, change precedence of operators. Type casting is applied before division normally but using parentheses you tell compiler to divide before casting to float.
Order of operations: Casting applies before division, and division between two integers always rounds (down) to the nearest integer in Java.
float r = (float)m/f; // Is the same as ((float)m)/f, and because there's a
// float in the division, we keep everything a float.
float r = (float)(m/f); // Is division between two integers, so we round down
// to the nearest integer before casting to a float.

Division of integers in Java [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);

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