How do I parse a string to a float or int?

后端 未结 29 2769
醉话见心
醉话见心 2020-11-21 04:43

In Python, how can I parse a numeric string like \"545.2222\" to its corresponding float value, 545.2222? Or parse the string \"31\" t

相关标签:
29条回答
  • 2020-11-21 05:02

    This is a function which will convert any object (not just str) to int or float, based on if the actual string supplied looks like int or float. Further if it's an object which has both __float and __int__ methods, it defaults to using __float__

    def conv_to_num(x, num_type='asis'):
        '''Converts an object to a number if possible.
        num_type: int, float, 'asis'
        Defaults to floating point in case of ambiguity.
        '''
        import numbers
    
        is_num, is_str, is_other = [False]*3
    
        if isinstance(x, numbers.Number):
            is_num = True
        elif isinstance(x, str):
            is_str = True
    
        is_other = not any([is_num, is_str])
    
        if is_num:
            res = x
        elif is_str:
            is_float, is_int, is_char = [False]*3
            try:
                res = float(x)
                if '.' in x:
                    is_float = True
                else:
                    is_int = True
            except ValueError:
                res = x
                is_char = True
    
        else:
            if num_type == 'asis':
                funcs = [int, float]
            else:
                funcs = [num_type]
    
            for func in funcs:
                try:
                    res = func(x)
                    break
                except TypeError:
                    continue
            else:
                res = x
    
    0 讨论(0)
  • 2020-11-21 05:03

    Here's another interpretation of your question (hint: it's vague). It's possible you're looking for something like this:

    def parseIntOrFloat( aString ):
        return eval( aString )
    

    It works like this...

    >>> parseIntOrFloat("545.2222")
    545.22220000000004
    >>> parseIntOrFloat("545")
    545
    

    Theoretically, there's an injection vulnerability. The string could, for example be "import os; os.abort()". Without any background on where the string comes from, however, the possibility is theoretical speculation. Since the question is vague, it's not at all clear if this vulnerability actually exists or not.

    0 讨论(0)
  • 2020-11-21 05:04

    If you aren't averse to third-party modules, you could check out the fastnumbers module. It provides a function called fast_real that does exactly what this question is asking for and does it faster than a pure-Python implementation:

    >>> from fastnumbers import fast_real
    >>> fast_real("545.2222")
    545.2222
    >>> type(fast_real("545.2222"))
    float
    >>> fast_real("31")
    31
    >>> type(fast_real("31"))
    int
    
    0 讨论(0)
  • 2020-11-21 05:04

    Handles hex, octal, binary, decimal, and float

    This solution will handle all of the string conventions for numbers (all that I know about).

    def to_number(n):
        ''' Convert any number representation to a number 
        This covers: float, decimal, hex, and octal numbers.
        '''
    
        try:
            return int(str(n), 0)
        except:
            try:
                # python 3 doesn't accept "010" as a valid octal.  You must use the
                # '0o' prefix
                return int('0o' + n, 0)
            except:
                return float(n)
    

    This test case output illustrates what I'm talking about.

    ======================== CAPTURED OUTPUT =========================
    to_number(3735928559)   = 3735928559 == 3735928559
    to_number("0xFEEDFACE") = 4277009102 == 4277009102
    to_number("0x0")        =          0 ==          0
    to_number(100)          =        100 ==        100
    to_number("42")         =         42 ==         42
    to_number(8)            =          8 ==          8
    to_number("0o20")       =         16 ==         16
    to_number("020")        =         16 ==         16
    to_number(3.14)         =       3.14 ==       3.14
    to_number("2.72")       =       2.72 ==       2.72
    to_number("1e3")        =     1000.0 ==       1000
    to_number(0.001)        =      0.001 ==      0.001
    to_number("0xA")        =         10 ==         10
    to_number("012")        =         10 ==         10
    to_number("0o12")       =         10 ==         10
    to_number("0b01010")    =         10 ==         10
    to_number("10")         =         10 ==         10
    to_number("10.0")       =       10.0 ==         10
    to_number("1e1")        =       10.0 ==         10
    

    Here is the test:

    class test_to_number(unittest.TestCase):
    
        def test_hex(self):
            # All of the following should be converted to an integer
            #
            values = [
    
                     #          HEX
                     # ----------------------
                     # Input     |   Expected
                     # ----------------------
                    (0xDEADBEEF  , 3735928559), # Hex
                    ("0xFEEDFACE", 4277009102), # Hex
                    ("0x0"       ,          0), # Hex
    
                     #        Decimals
                     # ----------------------
                     # Input     |   Expected
                     # ----------------------
                    (100         ,        100), # Decimal
                    ("42"        ,         42), # Decimal
                ]
    
    
    
            values += [
                     #        Octals
                     # ----------------------
                     # Input     |   Expected
                     # ----------------------
                    (0o10        ,          8), # Octal
                    ("0o20"      ,         16), # Octal
                    ("020"       ,         16), # Octal
                ]
    
    
            values += [
                     #        Floats
                     # ----------------------
                     # Input     |   Expected
                     # ----------------------
                    (3.14        ,       3.14), # Float
                    ("2.72"      ,       2.72), # Float
                    ("1e3"       ,       1000), # Float
                    (1e-3        ,      0.001), # Float
                ]
    
            values += [
                     #        All ints
                     # ----------------------
                     # Input     |   Expected
                     # ----------------------
                    ("0xA"       ,         10), 
                    ("012"       ,         10), 
                    ("0o12"      ,         10), 
                    ("0b01010"   ,         10), 
                    ("10"        ,         10), 
                    ("10.0"      ,         10), 
                    ("1e1"       ,         10), 
                ]
    
            for _input, expected in values:
                value = to_number(_input)
    
                if isinstance(_input, str):
                    cmd = 'to_number("{}")'.format(_input)
                else:
                    cmd = 'to_number({})'.format(_input)
    
                print("{:23} = {:10} == {:10}".format(cmd, value, expected))
                self.assertEqual(value, expected)
    
    0 讨论(0)
  • 2020-11-21 05:05

    This is another method which deserves to be mentioned here, ast.literal_eval:

    This can be used for safely evaluating strings containing Python expressions from untrusted sources without the need to parse the values oneself.

    That is, a safe 'eval'

    >>> import ast
    >>> ast.literal_eval("545.2222")
    545.2222
    >>> ast.literal_eval("31")
    31
    
    0 讨论(0)
  • 2020-11-21 05:05

    The YAML parser can help you figure out what datatype your string is. Use yaml.load(), and then you can use type(result) to test for type:

    >>> import yaml
    
    >>> a = "545.2222"
    >>> result = yaml.load(a)
    >>> result
    545.22220000000004
    >>> type(result)
    <type 'float'>
    
    >>> b = "31"
    >>> result = yaml.load(b)
    >>> result
    31
    >>> type(result)
    <type 'int'>
    
    >>> c = "HI"
    >>> result = yaml.load(c)
    >>> result
    'HI'
    >>> type(result)
    <type 'str'>
    
    0 讨论(0)
提交回复
热议问题