1

I'm trying to check if a double variable p is approximately equal to an integer. At some point in my code I have

double ip;
cout << setprecision(15) << abs(p) << " " << modf(abs(p), &ip) << endl;

And for a given run I get the printout

1 1

This seems to say that the fractional part of 1 is 1, am I missing something here or could there be some roundoff problem etc?

Note: I'm not including the whole code since the origin of p is complicated and I'm just asking if this is a familiar issue

jorgen
  • 3,425
  • 4
  • 31
  • 53
  • 1
    I suggest you set a higher precision and re-test, that might catch the not-quite-1. Also, I guess you omitted the initialization of `p` to something not quite 1 iny our snippet. – Deduplicator Oct 01 '14 at 13:04
  • @Deduplicator Oh yeah I get it now, for e.g. p=0.999999999 this would happen.. I'd delete this post but would that remove the upvotes on your comments? – jorgen Oct 01 '14 at 13:06
  • 1
    Don't delete a question just because it's answered in comments. Instead, encourage the commenter to write an actual answer, or if they don't, write the answer yourself. – aschepler Oct 01 '14 at 13:11
  • Ok! Actually I wanted to delete it because I thought it was a stupid question:) – jorgen Oct 01 '14 at 13:12
  • Also, comments are ephemeral, and upvotes on them are only important in context. – Deduplicator Oct 01 '14 at 13:36

2 Answers2

2

could there be some roundoff problem etc?

There certainly could. If the value is very slightly less than 1, then both its value and its fractional part could be rounded to 1 when displayed.

the origin of p is complicated

Then it's very likely not to be an exact round number.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
2

You are testing a nearly-1-value, so precision of 15 is not enough to describe it unambiguously.

This code shows your problem clearly:

#include <iostream>
#include <iomanip>
#include <cmath>
#include <limits>
using namespace std;

int main() {
    double ip, d = nextafter(1., .0); // Get a double just smaller than 1
    const auto mp = std::numeric_limits<double>::max_digits10;
    cout << 15 << ": " << setprecision(15)
        << abs(d) << " " << modf(abs(d), &ip) << '\n';
    cout << mp << ": " << setprecision(mp)
        << abs(d) << " " << modf(abs(d), &ip) << '\n';
}

On coliru: http://coliru.stacked-crooked.com/a/e00ded79c1727299

15: 1 1
17: 0.99999999999999989 0.99999999999999989
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
  • 2
    I guess with c++11 one could use [`std::numeric_limits::max_digits10`](http://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10) to get the necessary precision with out resorting to magic numbers. – luk32 Oct 01 '14 at 13:20
  • @luk32: Yes. Did so to make it more obvious. – Deduplicator Oct 01 '14 at 13:26