0

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"?

liori
  • 40,917
  • 13
  • 78
  • 105
  • This question reminds me **strongly** of one I answered in...2008? May have to go looking... – T.J. Crowder Jun 28 '19 at 11:58
  • @T.J.Crowder feel free to make it a duplicate, then. I couldn't find anything. – liori Jun 28 '19 at 12:00
  • https://stackoverflow.com/a/9909417/3182664 (ignore the accepted answer there) – Marco13 Jun 28 '19 at 12:02
  • @Marco13 Still not exactly an answer to his – Yassin Hajaj Jun 28 '19 at 12:05
  • @liori - It's such a vague memory... It was probably something else. :-) – T.J. Crowder Jun 28 '19 at 12:10
  • @YassinHajaj I don't want to argue. Feel free to add a reopen vote. But if the point of the question is whether you can or have to wrap 3 lines of code into a `doMyStuff` utility method, then this should be pointed out more clearly. There's certainly no built-in functionality for that in the standard API. – Marco13 Jun 28 '19 at 12:10
  • @Marco13, I thought I made it clear with asking for "any shorter idiom". – liori Jun 28 '19 at 12:17
  • The answer to this question is No. There isn't a shorter idiom ... apart from the obvious one of "make it a method and call it". I agree that this is a dup. – Stephen C Jun 28 '19 at 12:26
  • @liori You can check my answer in which I have used `intExactValue()` provided in `BigDecimal` class. It's a short and concise solution. – Mushif Ali Nawaz Jun 28 '19 at 12:27
  • @StephenC You're right. If we see the implementation of `intExactValue()` method, it's not that much short. And I think we should use their implementation rather than writing the logic to check these conditions ourselves. – Mushif Ali Nawaz Jun 28 '19 at 12:31
  • 1
    Yes ... but 1) it involves a **major** overhead of converting the `double` to a `BigDecimal`, and 2) it is not clear that it will give the same answer in all cases because of the difference between base 2 and base 10 representations. – Stephen C Jun 28 '19 at 12:34
  • @StephenC, if this is a dup, then how come none of the answers there answer my question? If the answer to my question is "no", then how about just writing an answer of "No" as an actual answer here? – liori Jun 28 '19 at 12:39
  • Please read [The "reasonable user" theory of duplicate questions](https://meta.stackoverflow.com/questions/384711/the-reasonable-user-theory-of-duplicate-questions/384792#384792). It applies to this case ... in my opinion. – Stephen C Jun 28 '19 at 12:42
  • @StephenC it would be if the decomposition was the answer. Not if the question is about *avoiding* decomposition. – liori Jun 28 '19 at 12:50

3 Answers3

1

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));
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
0

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(...);
Yassin Hajaj
  • 21,337
  • 9
  • 51
  • 89
0

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

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
Mushif Ali Nawaz
  • 3,707
  • 3
  • 18
  • 31