Pergunta

Em Python, como posso analisar uma seqüência numérica como "545.2222" ao seu correspondente valor float, 545.2222? Ou analisar o "31" string para um inteiro, 31?

Eu só quero saber como analisar um flutuador str a um float, e (separadamente) um int str a um int.

Foi útil?

Solução

>>> a = "545.2222"
>>> float(a)
545.22220000000004
>>> int(float(a))
545

Outras dicas

def num(s):
    try:
        return int(s)
    except ValueError:
        return float(s)

método de Python para verificar se uma string é um float:

def is_float(value):
  try:
    float(value)
    return True
  except:
    return False

Um nome mais longo e mais precisas para esta função poderia ser: is_convertible_to_float(value)

O que é, e não é um flutuador em Python pode surpreendê-lo:

val                   is_float(val) Note
--------------------  ----------   --------------------------------
""                    False        Blank string
"127"                 True         Passed string
True                  True         Pure sweet Truth
"True"                False        Vile contemptible lie
False                 True         So false it becomes true
"123.456"             True         Decimal
"      -127    "      True         Spaces trimmed
"\t\n12\r\n"          True         whitespace ignored
"NaN"                 True         Not a number
"NaNanananaBATMAN"    False        I am Batman
"-iNF"                True         Negative infinity
"123.E4"              True         Exponential notation
".1"                  True         mantissa only
"1,234"               False        Commas gtfo
u'\x30'               True         Unicode is fine.
"NULL"                False        Null is not special
0x3fade               True         Hexadecimal
"6e7777777777777"     True         Shrunk to infinity
"1.797693e+308"       True         This is max value
"infinity"            True         Same as inf
"infinityandBEYOND"   False        Extra characters wreck it
"12.34.56"            False        Only one dot allowed
u'四'                 False        Japanese '4' is not a float.
"#56"                 False        Pound sign
"56%"                 False        Percent of what?
"0E0"                 True         Exponential, move dot 0 places
0**0                  True         0___0  Exponentiation
"-5e-5"               True         Raise to a negative number
"+1e1"                True         Plus is OK with exponent
"+1e1^5"              False        Fancy exponent not interpreted
"+1e1.3"              False        No decimals in exponent
"-+1"                 False        Make up your mind
"(1)"                 False        Parenthesis is bad

Você acha que sabe o que os números são? Você não é tão bom como você pensa! Não grande surpresa.

Não use este código no software crítico de vida!

Catching amplas exceções desta forma, matando canários e devorando a exceção cria uma pequena chance de que um flutuador válida como corda vai retornar falso. A linha de float(...) de código pode falhou por qualquer uma das mil razões que nada têm a ver com o conteúdo da string. Mas se você é software crítico de vida escrita em uma linguagem protótipo pato-digitando como Python, então você tem problemas muito maiores.

Este é outro método que merece ser mencionado aqui, ast.literal_eval :

Isto pode ser usado para avaliar com segurança strings contendo expressões Python de fontes não confiáveis ??sem a necessidade de analisar os valores de si mesmo.

Isto é, um cofre 'eval'

>>> import ast
>>> ast.literal_eval("545.2222")
545.2222
>>> ast.literal_eval("31")
31
float(x) if '.' in x else int(x)

Localização e vírgulas

Você deve considerar a possibilidade de vírgulas na representação de cadeia de um número, para casos como float("545,545.2222") que lança uma exceção. Em vez disso, usar métodos em locale para converter as cordas para números e interpretar vírgulas corretamente. O método locale.atof convertidos para um flutuador em um passo uma vez que o local foi definido para a convenção numérica pretendida.

Exemplo 1 - United States convenções numéricas

Nos Estados Unidos e no Reino Unido, vírgulas pode ser usado como um separador de milhares. Neste exemplo com locale americano, a vírgula é tratada adequadamente como um separador:

>>> import locale
>>> a = u'545,545.2222'
>>> locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
'en_US.UTF-8'
>>> locale.atof(a)
545545.2222
>>> int(locale.atof(a))
545545
>>>

Exemplo 2 - European convenções numéricas

Na maioria dos países do mundo , vírgulas são usadas para marcas decimais em vez de períodos. Neste exemplo com locale francês, a vírgula é tratada corretamente como uma marca decimal:

>>> import locale
>>> b = u'545,2222'
>>> locale.setlocale(locale.LC_ALL, 'fr_FR')
'fr_FR'
>>> locale.atof(b)
545.2222

O método locale.atoi também está disponível, mas o argumento deve ser um inteiro.

Se você não são avessos a módulos de terceiros, você poderia verificar o fastnumbers módulo. Ele fornece uma função chamada fast_real que faz exatamente o que esta questão é pedindo e fá-lo mais rápido do que uma implementação puro-Python:

>>> 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

Usuários codelogic e harley estão corretos, mas tenha em mente se você souber a string é um número inteiro (por exemplo, 545) você pode chamar int ( "545" ) sem primeiro fundição para float.

Se as cordas estão em uma lista, você pode usar a função de mapa também.

>>> x = ["545.0", "545.6", "999.2"]
>>> map(float, x)
[545.0, 545.60000000000002, 999.20000000000005]
>>>

Ele só é bom se eles estão todos do mesmo tipo.

A pergunta parece um pouco velho. Mas deixe-me sugerir uma função, parseStr, o que faz algo semelhante, ou seja, os retornos inteiro ou bóia e se uma dada seqüência de caracteres ASCII não pode ser convertido em nenhum deles ele retorna intacto. O código é claro pode ser ajustado para fazer apenas o que você quer:

   >>> import string
   >>> parseStr = lambda x: x.isalpha() and x or x.isdigit() and \
   ...                      int(x) or x.isalnum() and x or \
   ...                      len(set(string.punctuation).intersection(x)) == 1 and \
   ...                      x.count('.') == 1 and float(x) or x
   >>> parseStr('123')
   123
   >>> parseStr('123.3')
   123.3
   >>> parseStr('3HC1')
   '3HC1'
   >>> parseStr('12.e5')
   1200000.0
   >>> parseStr('12$5')
   '12$5'
   >>> parseStr('12.2.2')
   '12.2.2'

Em Python, como posso analisar uma seqüência numérica como "545.2222" ao seu valor float correspondente, 542.2222? Ou analisar a cadeia "31" para um inteiro, 31? Eu só quero saber como analisar uma seqüência float para um float, e (separadamente) uma string int para um int.

É bom que você pedir para fazer estes separadamente. Se você está misturando-os, você pode estar se preparando para problemas mais tarde. A resposta é simples:

"545.2222" a flutuar:

>>> float("545.2222")
545.2222

"31" para um inteiro:

>>> int("31")
31

Outras conversões, ints de e para cordas e literais:

As conversões de várias bases, e você deve saber a base de antecedência (10 é o padrão). Nota você pode prefixar-los com o Python espera por suas literais (veja abaixo) ou remover o prefixo:

>>> int("0b11111", 2)
31
>>> int("11111", 2)
31
>>> int('0o37', 8)
31
>>> int('37', 8)
31
>>> int('0x1f', 16)
31
>>> int('1f', 16)
31

Se você não sabe a base de antecedência, mas você sabe que vai ter o prefixo correto, Python pode inferir isso para você se você passar 0 como base:

>>> int("0b11111", 0)
31
>>> int('0o37', 0)
31
>>> int('0x1f', 0)
31

literais de outras bases não-decimais (isto é, número inteiro)

Se a sua motivação é ter o seu próprio código claramente representam valores específicos codificados, no entanto, você pode não precisar de converter a partir das bases -. Você pode deixar Python fazer isso por você automaticamente com a sintaxe correta

Você pode usar os prefixos apropos para obter a conversão automática para inteiros com o seguintes literais . Estes são válidos para Python 2 e 3:

Binário, prefixo 0b

>>> 0b11111
31

Octal, prefixo 0o

>>> 0o37
31

hexadecimal, prefixo 0x

>>> 0x1f
31

Isto pode ser útil ao descrever bandeiras binários, permissões de arquivo em código, ou valores hexadecimais para as cores - por exemplo, observar sem aspas:

>>> 0b10101 # binary flags
21
>>> 0o755 # read, write, execute perms for owner, read & ex for group & others
493
>>> 0xffffff # the color, white, max values for red, green, and blue
16777215

Fazendo ambíguas Python 2 octals compatíveis com o Python 3

Se você ver um número inteiro que começa com um 0, em Python 2, este é (reprovado) octal sintaxe.

>>> 037
31

É ruim porque parece que o valor deve ser 37. Assim, em Python 3, que agora levanta uma SyntaxError:

>>> 037
  File "<stdin>", line 1
    037
      ^
SyntaxError: invalid token

Converta seus Python 2 octals para octals que o trabalho em ambos os 2 e 3 com o prefixo 0o:

>>> 0o37
31

float("545.2222") e int(float("545.2222"))

O YAML analisador pode ajudar você a descobrir que tipo de dados a cadeia é. Use yaml.load(), e então você pode usar type(result) de teste para o tipo:

>>> 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'>

Eu uso essa função para que

import ast

def parse_str(s):
   try:
      return ast.literal_eval(str(s))
   except:
      return

Ele irá converter a string para o seu tipo

value = parse_str('1')  # Returns Integer
value = parse_str('1.5')  # Returns Float
def get_int_or_float(v):
    number_as_float = float(v)
    number_as_int = int(number_as_float)
    return number_as_int if number_as_float == number_as_int else number_as_float
def num(s):
    """num(s)
    num(3),num(3.7)-->3
    num('3')-->3, num('3.7')-->3.7
    num('3,700')-->ValueError
    num('3a'),num('a3'),-->ValueError
    num('3e4') --> 30000.0
    """
    try:
        return int(s)
    except ValueError:
        try:
            return float(s)
        except ValueError:
            raise ValueError('argument is not a string of number')

Você precisa levar em conta o arredondamento para fazer isso corretamente.

i. int (5,1) => 5 int (5,6) => 5 - errado, deve ser de 6 por isso fazemos int (5,6 + 0,5) => 6

def convert(n):
    try:
        return int(n)
    except ValueError:
        return float(n + 0.5)

Estou surpreso que ninguém mencionou regex porque às vezes string deve ser preparado e normalizado antes de lançar para o número

import re
def parseNumber(value, as_int=False):
    try:
        number = float(re.sub('[^.\-\d]', '', value))
        if as_int:
            return int(number + 0.5)
        else:
            return number
    except ValueError:
        return float('nan')  # or None if you wish

uso:

parseNumber('13,345')
> 13345.0

parseNumber('- 123 000')
> -123000.0

parseNumber('99999\n')
> 99999.0

E, a propósito, algo para verificar se você tem um número:

import numbers
def is_number(value):
    return isinstance(value, numbers.Number)
    # will work with int, float, long, Decimal

Para typecast em python usar os funtions construtor do tipo, passando a cadeia (ou qualquer valor que você está tentando elenco) como parâmetro.

Por exemplo:

>>>float("23.333")
   23.333

Nos bastidores, python está chamando o método objetos __float__, que deve retornar uma representação flutuador do parâmetro. Isto é especialmente poderoso, como você pode definir seus próprios tipos (usando classes) com um método __float__ para que ele possa ser escalado em um flutuador usando float (myobject).

Esta é uma versão corrigida de https://stackoverflow.com/a/33017514/5973334

Esta tentará analisar uma string e retornar tanto int ou float dependendo do que a string representa. Pode ascensão analisar exceções ou ter algum comportamento inesperado .

  def get_int_or_float(v):
        number_as_float = float(v)
        number_as_int = int(number_as_float)
        return number_as_int if number_as_float == number_as_int else 
        number_as_float

Use:

def num(s):
    try:
        for each in s:
            yield int(each)
    except ValueError:
        yield float(each)
a = num(["123.55","345","44"])
print a.next()
print a.next()

Esta é a maneira mais Pythonic eu poderia vir acima com.

Use:

>>> str_float = "545.2222"
>>> float(str_float)
545.2222
>>> type(_) # Check its type
<type 'float'>

>>> str_int = "31"
>>> int(str_int)
31
>>> type(_) # Check its type
<type 'int'>

Esta é uma função que irá converter qualquer object (não apenas str) para int ou float, com base em se a cadeia real fornecido se parece com int ou float. Além disso, se é um objeto que tem ambos os métodos __float e __int__, o padrão é usar __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

Aqui está uma outra interpretação da sua pergunta (dica: é vaga). É possível que você está procurando algo parecido com isto:

def parseIntOrFloat( aString ):
    return eval( aString )

Funciona assim ...

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

Teoricamente, há uma vulnerabilidade de injeção. A string poderia, por exemplo, ser "import os; os.abort()". Sem qualquer fundo em que a cadeia vem, no entanto, a possibilidade é especulação teórica. Desde a pergunta é vaga, não é de todo claro se esta vulnerabilidade realmente existe ou não.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top