28

Is there some function like str.isnumeric but applicable to float?

'13.37'.isnumeric() #False  

I still use this:

def isFloat(string):
    try:
        float(string)
        return True
    except ValueError:
        return False
3
  • A more consistent and complete answer: ` def strType(xstr): try: int(xstr) return 'int' except: try: float(xstr) return 'float' except: try: complex(xstr) return 'complex' except: return 'str' print("4", strType("4")) print("12345678901234567890", strType("12345678901234567890")) print("4.1", strType("4.1")) print("4.1+3j", strType("4.1+3j")) print("a", strType("a")) ` Commented Nov 12, 2019 at 15:18
  • 3
    '13.37'.replace(".","").isnumeric(): Commented Aug 24, 2020 at 12:38
  • I like @GrigoryIlizirov answer the best because it doesn't invoke an exception. Commented Nov 11, 2020 at 0:46

6 Answers 6

12

As Imran says, your code is absolutely fine as shown.

However, it does encourage clients of isFloat down the "Look Before You Leap" path instead of the more Pythonic "Easier to Ask Forgiveness than Permission" path.

It's more Pythonic for clients to assume they have a string representing a float but be ready to handle the exception that will be thrown if it isn't.

This approach also has the nice side-effect of converting the string to a float once instead of twice.

Sign up to request clarification or add additional context in comments.

3 Comments

+1: @pingvinus: Please don't waste time writing such things. Just write your real application. If it throws a ValueError that means the input wasn't valid float and an overall exception handler can report this. There's no need to pre-check for float values, since the float function does this right when you need it. And always correctly.
Although i see the point in try catch, I think that doing it a lot "could" be expensive to handle the exception. I am surprised that the isfloat helper is not available,
@S.Lott That's not necessarily true. There are very good applications for a function like this when you need to make a decision based on an unknown value. This is far more readable.
4

A more complete generalization:

    def strType(xstr):
        try:
            int(xstr)
            return 'int'
        except:
            try:
                float(xstr)
                return 'float'
            except:
                try:
                    complex(xstr)
                    return 'complex'
                except:
                    return 'str'


    print("4", strType("4"))
    print("12345678901234567890", strType("12345678901234567890"))
    print("4.1", strType("4.1"))
    print("4.1+3j", strType("4.1+3j"))
    print("a", strType("a"))

Comments

2

Your code is absolutely fine. Regex based solutions are more likely to be error prone.

Quick testing with timeit reveals float(str_val) is indeed faster than re.match()

>>> timeit.timeit('float("-1.1")')
1.2833082290601467
>>> timeit.timeit(r"pat.match('-1.1')", "import re; pat=re.compile(r'^-?\d*\.?\d+(?:[Ee]-?\d+)?$');")
1.5084138986904527

And the regex used above fails one edge case, it can't match '-1.', although float() will happily convert it to proper float value.

10 Comments

I think I remember seeing a thread about this on a mailing list a long time ago. The gist was that float() and a regex were about the same speed.
It's not a Python-way I think - 6 lines of code to solve common problem. But, thanks.
Using re.compile will make the regexp pretty much the same speed as float().
@Imran: your performance comparison is not correct, while float would be faster, you need to compile regex outside of the execution loop, it needs to be re-used for that method to be practical.
Performance with compiled regex is even worse :P. How could that be? The setup statement in timeit.timeit is eval'ed just once, isn't it?
|
1

There's a catch though: float('nan') returns nan, no exception raised ;)

1 Comment

nan and inf (positive and negative) are floats, as 1.e9. GNU libc, IEEE 754... so that's valid
0

Extending from @Imran's results:

>>> timeit('float("-1.1")', number=10000000)
1.365271806716919

>>> timeit(r"isfloat('-1.1')", """def isfloat(s): t = s.partition('.');
           return t[1] and t[0].isdigit() and (not t[2] or t[2].isdigit());""",
           number=10000000)
2.565232992172241

>>> timeit(r"pat.match('-1.1')", "import re; pat=re.compile(r'^-?\d*\.?\d+(
    ...: ?:[Ee]-?\d+)?$');", number=10000000)
3.258622169494629

My partition solution is much faster than regex, but slower than float; however has the advantage of not raising errors (so you can use it in e.g.: comprehensions).

This handles edge conditions like 1., but not specialisations like NaN.

Comments

-2

isinstance(myVariable, float) will work if you're testing a floating point variable.

Edit: Spoke too soon, didn't fully understand what you were trying to get.

1 Comment

that's not what OP wants

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.