This question already has answers here:
How to test if a double is an integer
(18 answers)
Closed 3 years ago.
I'm getting a value of type double from an API which, in my specific case, should always return a whole number in a range well within int's — any non-whole number will mean something went very wrong inside that API call. I do want to know when this happens.
I know I can do a post-conversion check like, let say:
double value = …;
int whole_number = (int) value;
if(value != whole_number) throw …;
Is there any shorter idiom to "Convert a double to int only if it is an exact conversion, and raise an exception if not"?
Your solution seems simplest to me. You can do it as a one-liner:
if (value != (int)value)) throw ...
but if you want the exception to be thrown for you, the only thing I can think of is to go through a String, which seems really convoluted, especially since you can't just use String.valueOf(value) to get the string:
// Seems really convoluted
Integer.parseInt(new DecimalFormat("##.###").format(d));
You can use the following check if needed
if (value % 1 != 0) {
throw...
}
Using an Optional<Double> you could use the following logic
Integer result = Optional.of(value)
.filter(d -> d % 1 == 0)
.filter(this::isInRange)
.map(Integer::parseInt)
.orElseThrow(...);
You can use BigDecimal::intValueExact():
int wholeNumber = BigDecimal.valueOf(value).intValueExact();
It will automatically throw an exception: if it has a nonzero fractional part or it is outside the range of int
Related
This question already has answers here:
Why is Java's Double.compare(double, double) implemented the way it is?
(4 answers)
Closed 1 year ago.
i heared that i should use compare() method for comparing two objects.
instead of using - (substraction) directly. because -(substraction) can invoke overflow
public class Employee implements Comparable<Employee> {
...
public int compareTo(Employee other) {
return Double.compare(salary, other.salary); // don't use (-)
}
}
and when i saw this implemented CompareTo() code(in Interger.class)
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
and i could see '>'
but as i know it eventually would be using substraction like in c++... probably in interpreter.. if i'm right
and use this result 0 ,1,-1 as = < >
what's different?
why when i use compareTo() method i can avoid overflowing?
please give me a detail reason.
As said in this post, the problem with using subtraction is the following.
This is due to integer overflow. When thisVal is very large and anotherVal is negative then subtracting the latter from the former yields a result that is bigger than thisVal which may overflow to the negative range.
https://stackoverflow.com/a/2728810/9520059
Indeed, the compiler will probably use a subtraction at very low level when evaluating the '<', however, it will check for overflows.
This question already has answers here:
How can I check if multiplying two numbers in Java will cause an overflow?
(15 answers)
Closed 4 years ago.
int a = 200000;
double b = (double) (a*a);
I would like to be able to calculate if (aa) (integers) is already too large (stackOverflow) to hold in the variable; in this case I know that multiplying (aa) leads to an int that will not fit -> the number will be wrong;
What I do not understand is how I can calculate this off the top of my head. How can I see if a value will not fit in an int variable??
Is there a way to do this without using methods, by just using the plain code and common sense? ;-)
Best regards,
Wouter
Two possible solutions.
Catch exception thrown after a call to the Math.…Exact methods: Math.multiplyExact, Math.addExact, Math.decrementExact, and so on.
int a = 200000;
try {
int result = Math.multiplyExact(x, y);
} catch(ArithmeticException e) {
//if you get here, it is too big
}
Or, check against the constants for minimum and maximum possible integer values.
long test = (long)a*(long)a;
if (test > Integer.MAX_VALUE || test < Integer.MIN_VALUE)
// Overflow!
You could make use of the constant MAX_VALUE from the Integer wrapper class and cast to long instead (you will get a compile error if you cast to double but exceed it's range)
int a = 200000;
long b = (long) a * (long) a;
if (b > Integer.MAX_VALUE) {
// do something
}
MAX_VALUE corresponds to the highest value an integer can be, (2^31)-1
Java 8 gave us Math.addExact() for integers but not decimals.
Is it possible for double and BigDecimal to overflow? Judging by Double.MAX_VALUE and How to get biggest BigDecimal value I'd say the answer is yes.
As such, why don't we have Math.addExact() for those types as well? What's the most maintainable way to check this ourselves?
double overflows to Infinity and -Infinity, it doesn't wrap around. BigDecimal doesn't overflow, period, it is only limited by the amount of memory in your computer. See: How to get biggest BigDecimal value
The only difference between + and .addExact is that it attempts to detect if overflow has occurred and throws an Exception instead of wraps. Here's the source code:
public static int addExact(int x, int y) {
int r = x + y;
// HD 2-12 Overflow iff both arguments have the opposite sign of the result
if (((x ^ r) & (y ^ r)) < 0) {
throw new ArithmeticException("integer overflow");
}
return r;
}
If you want to check that an overflow has occurred, in one sense it's simpler to do it with double anyway because you can simply check for Double.POSITIVE_INFINITY or Double.NEGATIVE_INFINITY; in the case of int and long, it's a slightly more complicated matter because it isn't always one fixed value, but in another, these could be inputs (e.g. Infinity + 10 = Infinity and you probably don't want to throw an exception in this case).
For all these reasons (and we haven't even mentioned NaN yet), this is probably why such an addExact method doesn't exist in the JDK. Of course, you can always add your own implementation to a utility class in your own application.
The reason you do not need a addExact function for floating point digits is because instead of wrapping around, it overflows to Double.Infinity.
Consequently you can very easily check at the end of the operation whether it overflowed or not. Since Double.POSITIVE_INFINITY + Double.NEGATIVE_INFINITY is NaN you also have to check for NaN in case of more complicated expressions.
This is not only faster but also easier to read. Instead of having Math.addExact(Math.addExact(x, y), z) to add 3 doubles together, you can instead write:
double result = x + y + z;
if (Double.isInfinite(result) || Double.isNan(result)) throw ArithmeticException("overflow");
BigDecimal on the other hand will indeed overflow and throw a corresponding exception in that case as well - this is very unlikely to ever happen in practice though.
For double, please check the other answers.
BigDecimal has the addExact() protection already built in. Many arithmetic operation methods (e.g. multiply) of BigDecimal contain a check on the scale of the result:
private int checkScale(long val) {
int asInt = (int)val;
if (asInt != val) {
asInt = val>Integer.MAX_VALUE ? Integer.MAX_VALUE : Integer.MIN_VALUE;
BigInteger b;
if (intCompact != 0 &&
((b = intVal) == null || b.signum() != 0))
throw new ArithmeticException(asInt>0 ? "Underflow":"Overflow");
}
return asInt;
}
This question already has answers here:
Multiplication of two ints overflowing to result in a negative number
(5 answers)
Closed 9 years ago.
static int fn = 0;
static int sn = 0;
static boolean running = false;
public static void run()
{
while (running == true)
{
fn = numbers[0];
sn = numbers[1];
if (sign == 0)
{
input.setText(String.valueOf(fn));
}
}
}
static class one implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if (Display.sign == 0)
{
Display.numbers[0] = Display.numbers[0] *10;
Display.numbers[0] = Display.numbers[0] +1;
}
}
}
This is the code for a calculator that I am programming (not all of it of course). This is the part where I display the number on the screen which I have done, but weirdly this works up until 10 characters
So after I get the program to display 1111111111 I want to do it once more and it gives me this weird number -1773790777. I am confused about how the program comes up with this. As you can see, above Display.numbers[] is the array I am storing the two numbers in. So to go over a place I multiply the number in the array by 10 then add 1. So how does this give me a negative number in the first place and what can I do to solve this problem?
Is your number overflowing?
You can check it by looking at Integer.MAX_VALUE (assuming you are using an integer). If you go over that you will loop will get weird results like this. See - http://javapapers.com/core-java/java-overflow-and-underflow/ for more details.
It's overflowing!
1111111111*10 + 1 = 11111111111 which is 0x2964619C7 in hexadecimal. It's a 34-bit value which can't be stored in a 32-bit int
In Java arithmetic operations wrap around by default, so if the result overflowed then it'll be wrapped back to the other end of the value range. See How does Java handle integer underflows and overflows and how would you check for it?
However due to the use of 2's complement, the result will be the lower bits of the result 11111111111 mod 232 = 2521176519 = 0x964619C7 which is -1'773'790'777 in 32-bit int, that's why you see the number. You should read more on binary, that's the basic of nowadays computers
In Java 8 you'll have an easier way to detect overflow with the new *Exact methods
The platform uses signed two's complement integer arithmetic with int and long primitive types. The developer should choose the primitive type to ensure that arithmetic operations consistently produce correct results, which in some cases means the operations will not overflow the range of values of the computation. The best practice is to choose the primitive type and algorithm to avoid overflow. In cases where the size is int or long and overflow errors need to be detected, the methods addExact, subtractExact, multiplyExact, and toIntExact throw an ArithmeticException when the results overflow. For other arithmetic operations such as divide, absolute value, increment, decrement, and negation overflow occurs only with a specific minimum or maximum value and should be checked against the minimum or maximum as appropriate.
https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html
This question already has answers here:
In Java, what does NaN mean?
(11 answers)
Closed 5 years ago.
I have a double[] and it has a value which is NaN. When I add up the array's elements, the NaN makes the result NaN too.
How did it happen? How can I prevent this NaN from being added to the rest of my array?
NaN stands for Not-a-Number. It can arise in a variety of ways, for example as a result of 0./0., sqrt(-1), or as the result of a calculation involving other NaNs.
The easiest way to check whether v is a NaN is by using Double.isNaN(v):
public static double sum(double arr[]) {
double sum = 0.0;
for (double val : arr) {
if (!Double.isNaN(val)) {
sum += val;
}
}
return sum;
}
edit: #Stephen C makes a good point in the comments: before deciding to ignore that NaN, it would be prudent to understand where it came from. It could be that it is the result of a bug elsewhere in your code, and by blindly ignoring the NaN you could simply be masking the bug instead of fixing it.
NaN stands for "Not a Number", so "Not A Number" + 10 = "Not a Number"
You might want to consider debuggin your app to find what's in the double array :)
how can i prevent that this NaN not bein added to the rest of my double[]
This way:
double[] array = something;
double sum = 0;
for (int i = 0; i < array.length; i++) {
if (!Double.isNaN(array[i])) {
sum += array[i];
}
}
RTFM:
Javadoc for NaN
public static final double NaN
A constant holding a Not-a-Number (NaN) value of type double. It is equivalent to the value returned by Double.longBitsToDouble(0x7ff8000000000000L).
And relevant section of the JVM spec says any operation involving a NaN is also a NaN (a bit like a null in SQL)
You can't just ignore the NaN, it's an indicator of a problem with you're program. You need to find out what is causing the NaN and fix that.
NaN - Not a Number
btw try :
double[] array = new double[10];
String result = StringUtils.join(array);
System.out.println(result+ " BATMAN !");
Java isn't my strong suit, but in other languages this comes from assigning a value from a string. Try this:
parseDouble
public static double parseDouble(String s)
throws NumberFormatException
Returns a new double initialized to the value represented by the specified String, as performed by the valueOf method of class Double.
Parameters:
s - the string to be parsed.
Returns:
the double value represented by the string argument.
Throws:
NumberFormatException - if the string does not contain a parsable double.
Since:
1.2
See Also:
valueOf(String)
Taken from here.