Possible loss of precision - java

I am trying to run this code in java and getting following error, required int found double.
public class UseMath{
public static void main(String[]args){
int x = Math.pow (2,4);
System.out.println ("2 to the power of 4 is" + x);
}
}

If you take a look at the documentation, it says, that Math.pow() expects two doubles, and returns a double. When you pass ints to this function, it means no harm, because casting (converting) an int to double means no loss. But when you assign the value to an int, it means, it can lose precision.
Simply do this:
int x = (int)Math.pow(2,4);
or
double x = Math.pow(2,4);

Related

Decimal value issue

I've got a really annoying task to do, and stuck with it.
So: I need to write a function which gives back the value of a floating number after the decimal.
For example: the param would be:5.456-> and the returning value should be:456.
I can not use String (of course this would be easy this way).
Do you have any suggestions?
It requires some steps to do it with primitives like float or double. If you were allowed to use BigDecimal, this would just be one line of code.
Given double d = 5.456;
first, cut off the part before the floating point.
do this by int full = (int)d; which will be 5
the subtract full from it: d-full will now be only the part after the point, so .456
now use a loop to multiply the value by 10 until the "after the point" part is 0.
The special thing here is that when you use double, you have floating point precision issues. That means that d will have the value 0.4560000000000004 in between. To solve that, let's introduce an epsilon.
The full code looks like this:
private static final double EPS = 1e-5;
public static void main(String[] args) {
double d = 5.456;
System.out.println(afterDot(d));
}
private static int afterDot(double d) {
d = getDecimals(d);
while(getDecimals(d) > EPS){ //decimals will likely never be 0 because of precision, so compare with a really small EPS instead of 0
d *= 10;
}
//cast the result to an int to cut off the double precision issues
return (int)d;
}
private static double getDecimals(double d) {
int full = (int) d;
d = d-full;
return d;
}
This prints 456. I am very sure this can be optimized somehow, but it's a working first draft.
What you want is the remainder, multiplied by 10 until the remainder is 0. Using BigDecimal to prevent rounding issues that looks like this:
final BigDecimal input = new BigDecimal("5.456");
BigDecimal x = input.remainder(BigDecimal.ONE);
while (x.remainder(BigDecimal.ONE).compareTo(BigDecimal.ZERO) > 0) {
x = x.multiply(new BigDecimal(10));
}
System.out.println(x.longValue());
Here are two ways that don't adjust for floating point anomalies.
double s = 5.456;
System.out.println(s%1);
or
System.out.println(s-(int)s);
both print
0.4560000000000004
Or use BigDecimal and adjust the scale and subtract the integer value.
System.out.println(BigDecimal.valueOf(s)
.setScale(3)
.subtract(BigDecimal.valueOf((int)s)));
prints
.456

By dividing 7/2 gives 3.5, but why an incompatible error isn't shown in the first case compare to the second case and how .5 is omitted?

public class YourClassNameHere { //first case
public static void main(String[] args) {
int num=7;
int div=num/2;
System.out.println(div);
}
}
//output: 3
public class YourClassNameHere {//second case
public static void main(String[] args) {
double num=3.5;
int div=num;
System.out.println(div);
}
}
//output: incompatible types: possible lossy conversion from double to int
int is not meant to store fractions. It stores only whole numbers, such as 1, 2342, -2323,32 etc.
Where as double on the other hand is meant to store large number that contains fractions, eg 12.12, 12.0008, 0.6787 and so on.
So 12.005 is a valid double but when you "convert" this to an int it will lose the .005 and only be 12.
Similarly when you divide two numbers, and result should contains fractions, you should either store it in float or a double.
See this question for more info: Difference between int and double
Edit
In the first case you are dividing and int with an int. So the result you get will be an int. If you notice the output is 3 when the result is stored in an int, and 3.0 if the result is stored in double. So there is no type conversion happening, but the division takes place based on the input types.
in your first case you dividing two int it's mean any answer will be without decimal point so any answer will omit the decimal point .. in the second case you can't set double value in int variable because there is a decimal point in double and not in int .. when you want to have the answer with decimal point just use double no need for int u have both option for your need ..
When dividing an int with an int it cuts off everything after the decimal point, so the result stays an int, and since num is an int and 2 is an int the result is 3 which can be stored into div.
In the second scenario you are trying to store a double into an int, which is not possible. Try out following div = num / 2.0. By dividing by 2.0, which is a double, the result should also be a double and then youll get the same error.
You are using integer type to store the double type numbers.
Integers can only store whole numbers.
int brothers = 2, backlogs = 3, lockdown = 3;
int birthToDeathRatio = 0.72; wrong
//It will throw error incompatible types: possible lossy conversion from double to int
so to store the fractions you can use
float birthToDeathRatio = 0.72;//(6 to 7 decimal precision)
double birthToDeathRatio = 0.72;//(15 to 16 decimal precision)
or if you are obliged to store the result in integer you can explicity cast it
int div = (int)(7/2); or int div = (int)(3.5);
//output 3

Why does a very big double input return "Infinity" instead of error in Java?

Initializing a double variable with a value greater than 1E309 gives an error during compilation.
However, taking that value as an input does not produce any error. In fact, printing the double variable gives the String "Infinity".
Why does this happen?
import java.util.Scanner;
public class BigDouble {
public static void main(String[] args) {
double number;
Scanner keyboard = new Scanner(System.in);
System.out.print("Enter a number: ");
number = keyboard.nextDouble();
System.out.println(number);
}
}
You didn't get any errors because nextDouble() parses a Double, not a double. Double as a wrapper class, has several useful constants:
public static final double POSITIVE_INFINITY = 1.0 / 0.0;
public static final double NEGATIVE_INFINITY = -1.0 / 0.0;
public static final double NaN = 0.0d / 0.0;
Inside, nextDouble() uses Double.parseDouble(String) to provide a result regardless of the range the inputted number is in.
public double nextDouble() {
...
try {
return Double.parseDouble(processFloatToken(next(floatPattern())));
} catch (NumberFormatException nfe) {
...
}
}
If the number is out of the double range, you will be given either POSITIVE_INFINITY or NEGATIVE_INFINITY.
"NaN" -> Double.parseDouble("NaN") -> Double.NaN -> NaN
"1E6000" -> Double.parseDouble("1E6000") -> Double.POSITIVE_INFINITY -> Infinity
When you say, "Initializing a double variable with a value greater than 1E309", you probably mean like:
double number = 1E6000;
Here, "1E6000" appearing as-is, is called a "literal" value. You are writing a program, and asking it that it literally uses this value as a double.
Which is impossible as this value is too large. So there is no sense allowing you to do that. Instead, use a value that can actually be represented, or if you want infinity, use constant Double.POSITIVE_INFINITY instead. Rejecting the literal 1E6000 is not taking away any options from you.
However, when you're not dealing with a literal value, but the result of some computing, then the common contract of floating-point numbers, is that if the value computed is too big to be represented, you provide infinity to represent it. Not an error.
Here the programmer has no way to predict that the user will type in a number too large to be represented exactly. There is no better alternative to propose, than to represent the value computed as a result, as infinity.

Java double x 10/4=2?

I am new to Java and I would like to know why when you have double 10/4 you get 2? Does double always have to have decimals in order to get the right answer? Thanks.
public class Super {
public static void main(String[] args){
double x = 10/4;
System.out.println(x);
}
}
You are performing integer division before assigning the result. Integer division results in an int, the truncated result 2. To force floating point calculation and get 2.5, use double literals:
double x = 10.0 / 4.0;
or cast one to a double:
double x = (double) 10 / 4;
You are dividing with integers. You can declare those as doubles the following way (or use f for floats):
double x = 10d/4d;
System.out.println(x);
Integer division. Even though you're assigning the result to a double, you're still dividing two integers (10 and 4) so you get an integer result (floor of the actual result).
You can fix this by having one or both operands be a floating point value, for example like this:
double x = 10.0/4;
or by using type casting:
double x = (double)10/4;
Replace it by:
double x = 10.0/4.0;
Double always takes in a decimal. So it would have to be
public class Super {
public static void main(String[] args){
double x = 10.0/4.0;
System.out.println(x);
}
}
For double you need to use the following
10d/4d
Then the output is going to be 2.5 Otherwise you are just gonna end up diving two integers
The right side ofter the '=' is an integer expression, which gets converted to double only after it's calculated. So it calculates 10/4 as an integer, 2, and then converts that number to double. If you want it as a double from the beginning you have to write
double x = 10.0 / 4.0;
Only numbers that cannot be read as integer will be treated as double. Or even simpler
double x = 2.5; // :-)

different result in java how can it be rectified

Simple calculation gives different result in java.
int a=5363/12*5;
out.println(a);// result is 2230
But actually result should be 2234.5
How can this java result be rectified?
Two issues:
The expression 5363/12*5 gives an integer result (in particular, the division is integer).
The variable a is of type int (integer).
To fix:
double a=5363.0/12*5;
out.println(a);
Note that in general you can't expect to get exact results when using floating-point arithmetic. The following is a very good read: What Every Computer Scientist Should Know About Floating-Point Arithmetic.
5363, 12, and 5 are all being interpreted as ints. the calculation actually being performed here is:
5363/12 = 446.9… - truncated to the int value 446
446 * 5 = 2230
Try specifying a as a float, and indicate that the numbers in the calculation are also created as floats:
float a = 5363f/12f*5f
Take a as double.
Taking a as int will round it to the integer.
Because your all the literal numbers in the right hand side are integers (e.g. 5363 as opposed to 5363.0) expression is being calculated using integer arithmetic semantics i.e. / does whole number division. Thus 5262/12 equals 446 and 446*5 equals 2230. Also your variable a is an int which can only ever hold an integer value.
To fix this you need to do two things. Change the type of a to a decimal type e.g. float or double b) have at least one of 5363 and 12 represented as a decimal type e.g.
double a= 5363.0/12.0*5
Instead of using double you can re-order your expression.
Assuming 5363/12*5 = 5363*5/12 this will give you a closer answer. You have commented you want to round the result so instead you have to add half the value you are dividing by.
int a = (5363 * 5 + /* for rounding */ 6) / 12;
System.out.println(a);
prints
2235
An int is an Integer - nothing after the ..
You should be using
double a = 5363d/12*5;
It seems it has some int/double rounding issue:
double a=((double)5363/12)*5;
System.out.println("VALUE: "+a);
Prints:
VALUE: 2234.5833333333335
Edit: rounding the result to an integer value:
double a=((double)5363/12)*5;
long b=Math.round(a); //you can cast it to an int type if needed
System.out.println("ROUNDED: "+b);
Prints:
ROUNDED: 2235
Use double
double a = 5363/12*5;
System.out.println(a);
or
cast the integer, to prevent loss or precision.
int a = ((int) 5363/12*5);
System.out.println(a);

Categories