-2

What I'm trying to do would look like this in Python (where n is float/double):

def check_int(n):
    if not isinstance(n, numbers.Integral):
        raise TypeError()

Since C/C++ are typestrong, what kind of cast-and-compare magic would be the best for this purpose?

I'd preferably want to know how it's done in C.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Daniel B
  • 322
  • 4
  • 15
  • What would be the type of `n`? – Eugene Sh. Jul 13 '18 at 20:51
  • float/double, thanks for the observation, I'll edit the Q – Daniel B Jul 13 '18 at 20:53
  • 4
    Do you want C or C++? They are very different languages. You need to choose one – Justin Jul 13 '18 at 20:53
  • You should be able to find [additional information you need to do this](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) at this link. – Sam Varshavchik Jul 13 '18 at 20:53
  • 2
    This doesn't make a lot of sense. Only `float`, `double` and `long double` can not be integers. Everything else is already and integer. If you want to check if a floating point type represents an integer that is pretty trivial to do, you just make sure it equals its floor. – NathanOliver Jul 13 '18 at 20:53
  • 2
    Then it is hardly possible. Not every "integer" number has a representation in `float/double` – Eugene Sh. Jul 13 '18 at 20:54
  • There is plenty you can google. Previous SO questions. – Weather Vane Jul 13 '18 at 20:54
  • 1
    In C++ this would be a compile time error because it is a statically typed language. – user7860670 Jul 13 '18 at 21:00
  • 1
    Won't the python function return false whenever n is a floating point type, even if it has an integer value? – Ben Jones Jul 13 '18 at 21:05
  • Python (the normal one) is an interpreter. So when you pass any object to a Python function, it is already nicely packed and its type is known. In C, if you get, say, a pointer to the value, this is not much. In C++ you have [STL type_traits](https://en.cppreference.com/w/cpp/header/type_traits) – ddbug Jul 13 '18 at 21:23
  • 1
    Do you really mean the number is in a `float` or `double` at the time you want to test it? Or are you reading the number from a stream or file where it appears as some numeral such as the characters “3” “.” “4” or “3” “.” “0”, and so on? – Eric Postpischil Jul 13 '18 at 21:31
  • I thought the `(without scanf/gets/etc)` remark would suffice. It's not a stream/file input, it's a floating point variable to be checked if it's actually an integer number. – Daniel B Jul 13 '18 at 22:00
  • 1
    @DanielB I don't think your python code does what you think it does. Your function will raise a `TypeError` even if n is a float with an integer value. This is different than when you compare with the `floor` function as done in the accepted answer. To see what I am talking about, see what happens when you call `check_int(1.0)`. – Ben Jones Jul 14 '18 at 00:56

1 Answers1

-1

Use floor

#include <cmath>

if (floor(n) == n)
    // n is an integer (mathematically speaking)
john
  • 85,011
  • 4
  • 57
  • 81
  • While this might be "mathematically correct," with double implementation this won't always be correct ([here's an example](https://ideone.com/f6rxYK)) – scohe001 Jul 13 '18 at 21:06
  • The python function that @Daniel B posted is checking the type, not the value. Although, whether programmatic type-checking even makes sense in C is another question... – Ben Jones Jul 13 '18 at 21:09
  • @scohe001 You example is not really demonstrating *the* problem. It's more to demonstrate the imprecision of the fp operations. – Eugene Sh. Jul 13 '18 at 21:16
  • @EugeneSh. which is exactly the problem. How can you tell whether or not a fp is an integer when not even every integer can be represented? The only answer to this question is a frame challenge. – scohe001 Jul 13 '18 at 21:23
  • @scohe001 As I said, it won't work with a float constant as in my first comment. – Eugene Sh. Jul 13 '18 at 21:26
  • @scohe001: OP stated in a comment that the `n` they want to test is in a `float` or `double`. Testing whether the value in `float` or a `double` is of course possible. Whether the OP means what they say or they really want to test a number represented as numeral in a character string is another matter. – Eric Postpischil Jul 13 '18 at 21:27
  • @EugeneSh. you made that comment 4 seconds before mine :) – scohe001 Jul 13 '18 at 21:28
  • @EugeneSh.: Testing a `float` “constant” is not relevant. It is unlikely OP wants to test literals in source code. Likely they want to test values in `float` or `double` objects, as they say, or they want to test numerals in character strings (including input from streams) that have not yet been converted to `float` or `double`. – Eric Postpischil Jul 13 '18 at 21:29
  • @scohe001 Yeah, but my point is that your example might be seen as demonstrating the imprecision of `/` and `*`, not the floating point representation itself – Eugene Sh. Jul 13 '18 at 21:30
  • @EricPostpischil This constant can be simply assigned to `n` without limiting the generality. – Eugene Sh. Jul 13 '18 at 21:31
  • @EugeneSh.: I do not know what that means. The fact that a constant can be assigned to `n` does not appear to be informative to the discussion. – Eric Postpischil Jul 13 '18 at 21:32
  • @EricPostpischil What is not clear? If we add a line `n=16777216.9f` on top of the answer code, the test is going to yield "true" value, meaning that it was found to be "integer", thus making it incorrect. – Eugene Sh. Jul 13 '18 at 21:33
  • @EugeneSh.: That is not relevant because OP does not say they want to take a literal in source code and test whether it is an integer or not. They were asked what the `n` they want to test is, and they answered that it is a `float` or `double`. That means they are not attempting to test whether the literal “16777216.9f” in source code is an integer or not. They are attempting to test whether the value in `n`, where `n` is a `float` or a `double`, is an integer or not. – Eric Postpischil Jul 13 '18 at 21:35
  • @EricPostpischil I think I understand your point. But yeah, we don't know what the OP's intention is. I would guess it is something to do with input validation. – Eugene Sh. Jul 13 '18 at 21:39
  • `trunc(n)` would be preferable to `floor(n)`. Theoretically, `floor(n)` could hit the limit of a floating-point type without infinity and thus overflow, whereas `trunc(n)` always produces a representable result. – Eric Postpischil Jul 13 '18 at 22:05
  • @EricPostpischil - Eugine is correct. If it's possible to trigger a false positive using a literal value, it's possible to trigger a false positive with user input that results in a variable having that same value. – Peter Jul 14 '18 at 01:31
  • @Peter: It is not possible to trigger a false value using a literal value because no literal value is involved. As the OP has confirmed, the starting data for the test is a `float` or `double`, not a literal. That means the starting value is already `float` or `double`; it is not a numeral that is a literal in text source. – Eric Postpischil Jul 14 '18 at 02:12
  • @EricPostpischil - A literal value of `16777216.9f` is of type `float`. You are incorrectly assuming it is something distinct. – Peter Jul 14 '18 at 06:00
  • @Peter: Suppose (A) “16777216.9f” appears in source text (and assuming IEEE-754 basic 32-bit binary floating-point with round-to-nearest-ties-to-even is used). Then, during compilation, it is parsed to the `float` value 16777216. This is time (B). OP was questioned about the specific problem they wanted to solve and confirmed they want to test the value that exists at time B and not at time A. Therefore, whatever value or meaning you attribute to the source text at time A is irrelevant. OP has indicated they do not care about it. They want to test the value that exists at time B. – Eric Postpischil Jul 14 '18 at 10:31
  • @Peter: In other words, your concerns about the value of a literal are irrelevant. They are not part of the problem **as specified by the author of this Stack Overflow question**. The problem is **defined** to start with a value that is **already** present in a `float` without any regard to what prior values may have hypothetically been involved before that. – Eric Postpischil Jul 14 '18 at 10:34