XWX
XWX

Reputation: 1976

Determine if a double value isSafeInteger in C++?

In JavaScript there is this isSafeInteger method. How check the same thing in C++? The most straightforward way would be:

bool isSafeInteger(double d) noexcept {
    auto const i = static_cast<std::int64_t>(d);
    return i == d && i <= 9007199254740991 && i >= -9007199254740991;
}

But it doesn't feel right. Is there a better way to do it?

Upvotes: 1

Views: 106

Answers (1)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275200

bool isSafeInteger(double d) noexcept {
  if (d>=std::numeric_limits<std::int64_t>::max()) return false;
  if (d<=std::numeric_limits<std::int64_t>::min()) return false;
  if (isnan(d)) return false;
  auto as_int=[](double d){return static_cast<std::int64_t>(d);};
  return (as_int(d)==d) && (as_int(d+1)!=as_int(d)) && (as_int(d-1)!=as_int(d));
}

this checks it round trips to double, and that adjacent doubles don't round to the same integer, and that the double isn't a NaN (while svoiding triggering any NaN traps).

Finally, guard against out of bounds conversion, which is UB. We use >= and <= to be safe due to +1/-1 usage later.

This also works for float, but not for 128 (or 70ish) sized floats.

Upvotes: 4

Related Questions