Pythonでは、次のような数値文字列を解析するにはどうすればよいですか
"545.2222"
対応する float 値に、
545.2222
? "31"
または、文字列を整数に解析します31
か?
float str
を afloat
に、(別々に) int str
をに解析する方法を知りたいだけですint
。
Pythonでは、次のような数値文字列を解析するにはどうすればよいですか
"545.2222"
対応する float 値に、
545.2222
? "31"
または、文字列を整数に解析します31
か?
float str
を afloat
に、(別々に) int str
をに解析する方法を知りたいだけですint
。
>>> a = "545.2222"
>>> float(a)
545.22220000000004
>>> int(float(a))
545
def is_float(value):
try:
float(value)
return True
except:
return False
この関数のより長くて正確な名前は次のようになります。is_convertible_to_float(value)
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
あなたは数字が何であるか知っていると思いますか?あなたはあなたが思っているほど上手ではありません!大きな驚きではありません。
この方法で幅広い例外をキャッチし、カナリアを殺し、例外をゴブリングすると、文字列として有効な浮動小数点数が false を返す可能性がわずかに生じます。コード行は、文字列のfloat(...)
内容とは関係のないさまざまな理由で失敗する可能性があります。しかし、Python のようなダックタイピング プロトタイプ言語で命にかかわるソフトウェアを作成している場合は、はるかに大きな問題が発生します。
def num(s):
try:
return int(s)
except ValueError:
return float(s)
これは、ここで言及するに値する別のメソッドast.literal_evalです。
これは、値を自分で解析する必要なく、信頼できないソースからの Python 式を含む文字列を安全に評価するために使用できます。
つまり、安全な「評価」
>>> import ast
>>> ast.literal_eval("545.2222")
545.2222
>>> ast.literal_eval("31")
31
float(x) if '.' in x else int(x)
サードパーティのモジュールが嫌いでない場合は、fastnumbersモジュールをチェックしてください。この質問が求めていることを正確に実行し、純粋な Python 実装よりも高速に実行するfast_realという関数を提供します。
>>> 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
ユーザーcodelogicとharleyは正しいですが、文字列が整数 (545 など) であることがわかっている場合は、最初に float にキャストせずに int("545") を呼び出すことができることに注意してください。
文字列がリストにある場合は、map 関数も使用できます。
>>> x = ["545.0", "545.6", "999.2"]
>>> map(float, x)
[545.0, 545.60000000000002, 999.20000000000005]
>>>
それらがすべて同じタイプである場合にのみ、それは良いことです。
Python では、"545.2222" のような数値文字列を対応する float 値 542.2222 に解析するにはどうすればよいですか? または、文字列「31」を整数の 31 に解析しますか? float 文字列を float に解析する方法と、(個別に) int 文字列を int に解析する方法を知りたいだけです。
これらを別々に行うように依頼するのは良いことです。それらを混在させている場合は、後で問題が発生する可能性があります。簡単な答えは次のとおりです。
"545.2222"
浮く:
>>> float("545.2222")
545.2222
"31"
整数に:
>>> int("31")
31
さまざまな基数からの変換。事前に基数を知っておく必要があります (10 がデフォルトです)。Python がそのリテラルに期待するプレフィックスを付けたり (以下を参照)、プレフィックスを削除したりできることに注意してください。
>>> int("0b11111", 2)
31
>>> int("11111", 2)
31
>>> int('0o37', 8)
31
>>> int('37', 8)
31
>>> int('0x1f', 16)
31
>>> int('1f', 16)
31
事前にベースがわからないが、正しい接頭辞があることはわかっている場合0
、ベースとして渡すと、Python はこれを推測できます。
>>> int("0b11111", 0)
31
>>> int('0o37', 0)
31
>>> int('0x1f', 0)
31
ただし、ハードコードされた特定の値を独自のコードで明確に表現することが動機である場合は、基数から変換する必要がない場合があります。正しい構文を使用して、Python に自動的に変換させることができます。
apropos 接頭辞を使用して、次のリテラルで整数への自動変換を取得できます。これらは Python 2 および 3 で有効です。
バイナリ、プレフィックス0b
>>> 0b11111
31
8 進数、プレフィックス0o
>>> 0o37
31
16 進数、プレフィックス0x
>>> 0x1f
31
これは、バイナリ フラグ、コード内のファイル パーミッション、または色の 16 進値を記述する場合に役立ちます。たとえば、引用符がないことに注意してください。
>>> 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
Python 2 で 0 で始まる整数が表示される場合、これは (非推奨の) 8 進構文です。
>>> 037
31
値が であるように見えるので、悪いです37
。したがって、Python 3 では、次のようになりますSyntaxError
。
>>> 037
File "<stdin>", line 1
037
^
SyntaxError: invalid token
Python 2 の 8 進数を、2 と 3 の両方で動作する 8 進数に次のプレフィックスを付けて変換します0o
。
>>> 0o37
31
質問は少し古いようです。しかし、関数 parseStr を提案させてください。これは、整数または浮動小数点数を返し、指定された ASCII 文字列をいずれにも変換できない場合はそのまま返します。もちろん、必要なことだけを行うようにコードを調整することもできます。
>>> 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'
float("545.2222")
とint(float("545.2222"))
YAMLパーサーは、文字列のデータ型を把握するのに役立ちます。を使用してから、タイプをテストするためにyaml.load()
使用できます。type(result)
>>> 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'>
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')
これを適切に行うには、丸めを考慮する必要があります。
つまり、int(5.1) => 5 int(5.6) => 5 -- 間違っています。6 のはずなので、int(5.6 + 0.5) => 6 とします。
def convert(n):
try:
return int(n)
except ValueError:
return float(n + 0.5)
使用する:
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()
これは私が思いついた最も Pythonic な方法です。
これがあなたの質問の別の解釈です(ヒント:あいまいです)。次のようなものを探している可能性があります。
def parseIntOrFloat( aString ):
return eval( aString )
それはこのように動作します...
>>> parseIntOrFloat("545.2222")
545.22220000000004
>>> parseIntOrFloat("545")
545
理論的には、インジェクションの脆弱性があります。文字列は、たとえば"import os; os.abort()"
. ただし、文字列がどこから来たのかについての背景はありませんが、その可能性は理論的な推測です. 質問が漠然としているため、この脆弱性が実際に存在するかどうかはまったく明らかではありません。