Explain Codes LogoExplain Codes Logo

How to test if a double is an integer

java
floating-point-arithmetic
precision
mathematical-integer
Nikita BarsukovbyNikita Barsukov·Oct 20, 2024
TLDR

Perform an instant check if a double is practically an integer. Compare it with its rounded variant using the Math.rint() method or verify there’s no decimal part by wielding the Math.floor(). Remember to exclude infinite values. Less they give you unexpected results.

double value = // your double value, maybe from input or calculation boolean isInteger = (value == Math.rint(value)) && !Double.isInfinite(value); // Oh look! That checks if our double is an integer. Or... boolean isInteger = (value == Math.floor(value)) && value != Math.ceil(value); // This one does too. Choose wisely.

In both one-liners, we are concluding that double has no fractional part and isn't infinite. So, it's an integer. Simplicity at its finest!

Beyond the Basics: Exploring Edge Cases

The Casting Method

When comparing the double to its casted int variant seems like a good idea, but be careful, not all cars can handle rough terrains.

double value = // your double value boolean isInteger = (value == (int)value) && !Double.isInfinite(value);

Remember, this approach offers a shortcut, but it's like walking on thin ice. Especially when handling sizeable numbers that have no respect for the limited int range.

The Precision Point

Floating-point arithmetic can be a tricky beast. Small rounding errors might sniff out to provide misleading results. So let's handle this with a little precision.

// A small delta, the hero we need for floating-point arithmetic comparison final double EPSILON = 1E-10; double value = // your double value boolean isInteger = Math.abs(value - Math.rint(value)) < EPSILON && !Double.isInfinite(value);

See what we did there? We've adjusted the equality check to allow for a tiny error. That's a handy trick when playing with double values. Smells like precision spirit!

Library utilities

Google's Guava library just stands at the corner, whistling and offering a utility check if a double is mathematically an integer:

import com.google.common.math.DoubleMath; ... double value = // your double value boolean isInteger = DoubleMath.isMathematicalInteger(value);

This code snippet is efficient, putting most pitfalls of floating-point arithmetic to bed. Keep in mind, though, that it's like a radar detector; useful, but not included in every car by default.

Advanced Insights: Precision is Key

Handling outliers: NaN and infinity

Robustness isn't only about lifting heavy weights. It also means handling NaN and infinity cases with grace as they can muddy the water:

double value = // your double value boolean isInteger = !Double.isNaN(value) && !Double.isInfinite(value) && (value == Math.floor(value));

Therefore, not only do we need our double value to be an integer, but we also need it to be a respectable numeric value.

Choosing the Right Method: pick your potion

It's vital to choose the suitable method based on your context and needs.

  • Math.rint() and Math.floor() are like all-rounder players, good for most scenarios.
  • Casting and comparison are the roadrunners of methods, but they don't like big numbers.
  • Google Guava's DoubleMath.isMathematicalInteger() is the racehorse, efficient, and avoids arithmetic pitfalls, but requires the library.
  • Apply delta comparison when precision is a hot topic.

Every method, just like every tool in a toolbox, has its place and purpose. The best choice depends on what you’re trying to build. So, pick your potion wisely!