1

I am typing code that checks if the number is positive, negative and if it has decimals or not. Is there a quicker way to check for decimals?

n = input("Type a number: ")
try:
    n = int(n)
    if n > 0:
        print("n is positive")
    elif n < 0:
        print("n is negative")
    else:
        print("n is zero")
except ValueError:
    n = float(n)
    if n > 0:
        print("n is positive and decimal")
    elif n < 0:
        print("n is negative and decimal")
    else:
        print("n is zero")
print(n)
input()
  • Welcome to SO! Why do you need a quicker way? Is there a performance issue here? – ggorlen Jan 23 '21 at 16:17
  • print(isinstance(num, float) – Daniel Hao Jan 23 '21 at 16:17
  • @ggorlen they are getting string input. – Countour-Integral Jan 23 '21 at 16:17
  • 2
    @roganjosh by failing and going into the except-part when the input is `"1.2"` – L3viathan Jan 23 '21 at 16:19
  • @L3viathan fair. I was too hasty, sorry – roganjosh Jan 23 '21 at 16:21
  • `'.' in str(n)` would tell you if it contains a decimal point. But honestly your existing code seems fine. You'd still want to create a `float` from it to continue checking whether it's positive/negative/zero. – CrazyChucky Jan 23 '21 at 16:21
  • The OP's approach looks fine indeed; see e.g. [this SO answer in "Check if a number is int or float", assuming a string input](https://stackoverflow.com/a/4541207/9164010) which suggests precisely a similar approach. – ErikMD Jan 23 '21 at 16:23
  • 1
    How about `(a := float('3.79')) == int(a)` or for whatever number. – Countour-Integral Jan 23 '21 at 16:24
  • @Countour-Integral nice suggestion; unfortunately that won't work well in general (see my [other comment](https://stackoverflow.com/questions/65861449/quickest-way-to-check-if-a-number-has-a-decimal-or-not/65861899#comment116448198_65861528) regarding numeric precision). – ErikMD Jan 23 '21 at 17:08
  • Anyway this question certainly looks like a duplicate of [Check if a number is int of float](https://stackoverflow.com/q/4541155/9164010) (albeit there is here the additional constraint that the input is a string, but [some answer](https://stackoverflow.com/a/4541207/9164010) in the proposed duplicate question deals with this case). – ErikMD Jan 23 '21 at 17:11
  • @ErikMD it wont work for very large inputs like `float(5000*'9')` (returns `float('inf')`). The only way I can think of in that case is by manually validating the string by looping through each char of the string and seeing if it is a number, validating the if the `.` is correct etc like @CrazyChucky suggested. – Countour-Integral Jan 23 '21 at 17:17
  • 1
    Yes, that's what I meant. And to implement what @CrazyChucky and you suggested, the best tool might just be regular expressions :) – ErikMD Jan 23 '21 at 17:18
  • What do you mean by "quicker"? – Karl Knechtel Jan 24 '21 at 05:01

4 Answers4

1

To follow-up the comments (1, 2): the code proposed in OP's question is fine.

However, if we want to avoid the cost of converting the string to numeric types and using exceptions, one could just as well rely on regular expressions to directly assert the sign and the kind of the provided literal.

For example, by writing something like:

#!/usr/bin/env python3
import re

def process(txt):

    pat = re.compile(r'^(-)?[0-9]+(\.[0-9]+)?$')

    grep = pat.match(txt)

    print(txt, 'is:')

    if grep is None:
        print('not a numeric string')
    else:
        if grep.group(1) is None:
            print('some ', end='')
        else:
            print('some negative ', end='')
        if grep.group(2) is None:
            print('integer')
        else:
            print('decimal')

process('-12')
process('-12.5')
process('12')
process('12.5')
process('foo')
process(500*'9')
process(str(input("Type a number: ")))
ErikMD
  • 13,377
  • 3
  • 35
  • 71
  • Be careful with that. The regular expression that describes the strings accepted by `float()`/`int()` is a little more complex than that (e.g. `".1e-3"` is a valid float). – L3viathan Jan 23 '21 at 22:12
  • @L3viathan Sure: this can easily be taken into account by slightly changing the regexp. Actually I didn't mention this because the OP's question only mentioned "decimals" but not scientific notation or floating-point arithmetic… – ErikMD Jan 23 '21 at 22:17
0

You can always use float and then check the .is_integer() method:

n = float(input("Type a number: "))


if n > 0:
    print("n is positive")
elif n < 0:
    print("n is negative")
else:
    print("n is zero")

if n.is_integer():
    print("n is integral")
else:
    print("n isn't integral")

print(n)
input()

To be clear: Now n will always have the type float, even if the user enters e.g. 2. is_integer just tells you whether the floating point number is representable as an integer.

This will cease to reliably work at the limits of floating point numbers:

>>> float("12345678901234567.5").is_integer()
True
>>> float("1"+ "0"*309).is_integer()
False
L3viathan
  • 26,748
  • 2
  • 58
  • 81
  • 1
    IINM, this cannot work in general (especially for large inputs): indeed, [Python3 floats rely on IEEE-754 double-precision](https://docs.python.org/3/tutorial/floatingpoint.html#representation-error) (i.e., finite precision), while [Python3 integers have unlimited precision](https://docs.python.org/3/library/stdtypes.html#numeric-types-int-float-complex). – ErikMD Jan 23 '21 at 17:05
  • @ErikMD Correct. The input has to be quite large (>300 digits) for this to matter, though. – L3viathan Jan 23 '21 at 22:10
  • 1
    yes, bot not necessarily with 300+ digits! you can end up with a wrong answer just with 18 digits: try `float("12345678901234567.5").is_integer()` – ErikMD Jan 23 '21 at 22:12
  • Oh, I was going the other way around ("when does an integer cease to be an integer?"). That is indeed a flaw that can reasonably occur on normal user input :/ Edited the answer. – L3viathan Jan 23 '21 at 22:26
0

Well assuming you are looking for "decimals" specifically rather than just floating point numbers, you can use this school taught algorithm made using the floor function.

>>> import math
>>> def is_int(x):
...     y=math.floor(x)+math.floor(-x)
...     if y==0:
...             print("It's an integer")
...     if y==-1:
...             print("It's a decimal")
...
>>> is_int(1)
It's an integer
>>> is_int(1.3)
It's a decimal
DankCoder
  • 369
  • 1
  • 4
  • 15
0

Here is another version using % operator.

n = float(input("Enter a number: "))

if n>=0:
    if n > 0 :
        print("Positive Number")
     else:
        print("Zero")
else:
    print("Negative Number")

if n%1!=0:
   print("Decimal Number")
else:
   print("Integer")
PGS
  • 79
  • 3