web-dev-qa-db-ja.com

文字列が数値(float)かどうかをどうやって確認するのですか?

Pythonで文字列が数値として表現できるかどうかを確認するための最善の方法は何ですか?

私が現在持っている機能は:

def is_number(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

これは、醜くて遅いだけでなく、不格好なようです。しかし、メイン関数でfloatを呼び出すのはさらに悪いので、もっと良い方法は見つけられませんでした。

1399
Daniel Goldberg

それは、醜くて遅いだけではありません

私は両方とも争います。

正規表現や他の文字列の解析は、より曖昧で遅くなります。 

私は、何かが上記よりも速くなることができるかどうかわからない。関数を呼び出して戻ります。 Try/Catchを使用しても、ほとんどのオーバーヘッドは発生しません。最も一般的な例外は、スタックフレームを広範囲に検索しなくても発生するためです。

問題は、どの数値変換関数にも2種類の結果があることです。

  • 番号が有効な場合は番号
  • 有効な番号を解析できなかったことを示すステータスコード(たとえば、errnoを介した)または例外。

C(例として)は、これを回避するためのいくつかの方法があります。 Pythonはそれを明確かつ明示的にレイアウトしています。

これを行うためのコードは完璧だと思います。

608
S.Lott

浮動小数点数の代わりに(正の符号なし)整数の解析を探している場合は、文字列オブジェクトに isdigit() 関数を使用できます。

>>> a = "03523"
>>> a.isdigit()
True
>>> b = "963spam"
>>> b.isdigit()
False

文字列メソッド - isdigit()

Unicode文字列に関するものもあります。 Unicode - decimal/decimal にはあまり精通していません。

1421
Zoomulator

TL; DR 最良の解決策はs.replace('.','',1).isdigit()です

ベンチマーク さまざまなアプローチの比較

def is_number_tryexcept(s):
    """ Returns True is string is a number. """
    try:
        float(s)
        return True
    except ValueError:
        return False

import re    
def is_number_regex(s):
    """ Returns True is string is a number. """
    if re.match("^\d+?\.\d+?$", s) is None:
        return s.isdigit()
    return True


def is_number_repl_isdigit(s):
    """ Returns True is string is a number. """
    return s.replace('.','',1).isdigit()

文字列が数値ではない場合、except-blockは非常に遅いです。しかしもっと重要なことに、try-exceptメソッドは科学的表記法を正しく扱う唯一のアプローチです。

funcs = [
          is_number_tryexcept, 
          is_number_regex,
          is_number_repl_isdigit
          ]

a_float = '.1234'

print('Float notation ".1234" is not supported by:')
for f in funcs:
    if not f(a_float):
        print('\t -', f.__name__)

浮動小数点表記「.1234」は、以下ではサポートされていません。
- is_number_regex 

scientific1 = '1.000000e+50'
scientific2 = '1e50'


print('Scientific notation "1.000000e+50" is not supported by:')
for f in funcs:
    if not f(scientific1):
        print('\t -', f.__name__)




print('Scientific notation "1e50" is not supported by:')
for f in funcs:
    if not f(scientific2):
        print('\t -', f.__name__)

科学表記 "1.000000e + 50"は、以下によってサポートされていません。
- is_number_regex
- is_number_repl_isdigit
科学表記「1e50」は、以下によってサポートされていません。
- is_number_regex
- is_number_repl_isdigit 

編集:ベンチマーク結果

import timeit

test_cases = ['1.12345', '1.12.345', 'abc12345', '12345']
times_n = {f.__name__:[] for f in funcs}

for t in test_cases:
    for f in funcs:
        f = f.__name__
        times_n[f].append(min(timeit.Timer('%s(t)' %f, 
                      'from __main__ import %s, t' %f)
                              .repeat(repeat=3, number=1000000)))

以下の機能がテストされた場所

from re import match as re_match
from re import compile as re_compile

def is_number_tryexcept(s):
    """ Returns True is string is a number. """
    try:
        float(s)
        return True
    except ValueError:
        return False

def is_number_regex(s):
    """ Returns True is string is a number. """
    if re_match("^\d+?\.\d+?$", s) is None:
        return s.isdigit()
    return True


comp = re_compile("^\d+?\.\d+?$")    

def compiled_regex(s):
    """ Returns True is string is a number. """
    if comp.match(s) is None:
        return s.isdigit()
    return True


def is_number_repl_isdigit(s):
    """ Returns True is string is a number. """
    return s.replace('.','',1).isdigit()

enter image description here

96
Sebastian

考慮しなければならない可能性がある例外が1つあります。文字列 'NaN'です。

Is_numberが 'NaN'に対してFALSEを返すようにしたい場合、Pythonはそれを数ではない数の表現に変換するので機能しません(アイデンティティの問題について話してください)

>>> float('NaN')
nan

さもなければ、私が実際に私が今広く使用しているコードの部分をありがとうございます。 :)

G.

66
gvrocha

これはどう:

'3.14'.replace('.','',1).isdigit()

これは、 '。'が1つあるかない場合にのみtrueを返します。数字のストリングで。

'3.14.5'.replace('.','',1).isdigit()

falseを返します

編集:ちょうど別のコメントを見た... 他の場合には.replace(badstuff,'',maxnum_badstuff)を追加することができます。もしあなたがsaltを渡していて、任意の調味料ではないなら(ref: xkcd#974 )これはうまくいくでしょう:P

53
haxwithaxe

Alfeがfloatをチェックする必要はないと指摘した後に更新されました。

def is_number(s):
    try:
        complex(s) # for int, long, float and complex
    except ValueError:
        return False

    return True

以前に言われました:あなたが同じくfloatで表されることができない複素数(例えば1 + 2i)をチェックする必要があるかもしれないいくつかのまれなケースです:

def is_number(s):
    try:
        float(s) # for int, long and float
    except ValueError:
        try:
            complex(s) # for complex
        except ValueError:
            return False

    return True
39

これは、醜くて遅いだけでなく、不格好なようです。

慣れるまでに時間がかかるかもしれませんが、これがPythonicのやり方です。すでに指摘したように、代替案はもっと悪いです。しかし、このようにすることにはもう1つの利点があります。それは多態性です。

アヒルのタイピングの背後にある中心的な考え方は、「アヒルのように歩き、話すならば、それはアヒルだ」ということです。何かをfloatに変換できるかどうかを判断する方法を変更できるように、stringをサブクラス化する必要があると判断した場合はどうしますか?あるいは、他のオブジェクトを完全にテストすることにした場合はどうなりますか?上記のコードを変更しなくても、これらのことを実行できます。

他の言語はインターフェースを使用することによってこれらの問題を解決します。どの解決策が別のスレッドに適しているかについての分析は省きます。ただし、重要なのは、Pythonは方程式のアヒルタイピング側にあるということです。Pythonで多くのプログラミングを行う予定であれば、おそらくこのような構文に慣れる必要があるでしょう(ただし、それは意味ではありません)。あなたはもちろんそれを好む必要があります。

考慮すべきもう1つのことがあります。Pythonは、他の多くの言語と比較して例外のスローとキャッチが非常に高速です(たとえば、.Netよりも30倍高速です)。一体、言語自体も例外をスローして、例外ではない通常のプログラム条件を伝達します(forループを使用するたびに)。したがって、重大な問題に気付くまでは、このコードのパフォーマンス面についてあまり気にする必要はありません。

37
Jason Baker

intにはこれを使います。

>>> "1221323".isdigit()
True

しかしfloatにはいくつかのトリックが必要です;-)。すべての浮動小数点数は1つの点を持ちます...

>>> "12.34".isdigit()
False
>>> "12.34".replace('.','',1).isdigit()
True
>>> "12.3.4".replace('.','',1).isdigit()
False

負の数の場合もlstrip()を追加するだけです。

>>> '-12'.lstrip('-')
'12'

そして今、私たちは普遍的な方法を手に入れます。

>>> '-12.34'.lstrip('-').replace('.','',1).isdigit()
True
>>> '.-234'.lstrip('-').replace('.','',1).isdigit()
False
19
Sdwdaw

C#をまねる

C#には、スカラー値の解析を処理する2つの異なる関数があります。

  • Float.Parse()
  • Float.TryParse()

float.parse():

def parse(string):
    try:
        return float(string)
    except Exception:
        throw TypeError

注:なぜ例外をTypeErrorに変更したのか疑問に思う場合は、 ここにドキュメントがあります

float.try_parse():

def try_parse(string, fail=None):
    try:
        return float(string)
    except Exception:
        return fail;

注:それでも値型であるため、ブール値の「False」を返したくはありません。失敗を示すものはありません。もちろん、違うものが必要な場合は、failパラメーターを任意の値に変更できます。

Parse()とtry_parse()を含むようにfloatを拡張するには、これらのメソッドを追加するためにfloatクラスをモンキーパッチする必要があります。

既存の関数を尊重したい場合は、コードは次のようになります。

def monkey_patch():
    if(!hasattr(float, 'parse')):
        float.parse = parse
    if(!hasattr(float, 'try_parse')):
        float.try_parse = try_parse

SideNote:私は個人的にモンキーパンチングと呼ぶことを好みます。なぜなら、私はこれをするとYMMVをするときに言語を悪用しているように感じるからです。

使用法:

float.parse('giggity') // throws TypeException
float.parse('54.3') // returns the scalar value 54.3
float.tryParse('twank') // returns None
float.tryParse('32.2') // returns the scalar value 32.2

そして偉大なSage PythonasはSharpisusに言った、「あなたができることなら何でも私はもっとよくできます。私はあなたよりももっとよくできます」

15
Evan Plaice

数字以外の文字列の場合、try: except:は実際には正規表現より遅くなります。有効な数値の文字列の場合、正規表現は遅くなります。したがって、適切な方法は入力内容によって異なります。 

自分がパフォーマンスの限界にあるとわかった場合は、 fastnumbers という新しいサードパーティ製モジュールを使用して、 isfloat という関数を使用できます。完全な開示、私は作者です。その結果を以下のタイミングに含めました。


from __future__ import print_function
import timeit

prep_base = '''\
x = 'invalid'
y = '5402'
z = '4.754e3'
'''

prep_try_method = '''\
def is_number_try(val):
    try:
        float(val)
        return True
    except ValueError:
        return False

'''

prep_re_method = '''\
import re
float_match = re.compile(r'[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?$').match
def is_number_re(val):
    return bool(float_match(val))

'''

fn_method = '''\
from fastnumbers import isfloat

'''

print('Try with non-number strings', timeit.timeit('is_number_try(x)',
    prep_base + prep_try_method), 'seconds')
print('Try with integer strings', timeit.timeit('is_number_try(y)',
    prep_base + prep_try_method), 'seconds')
print('Try with float strings', timeit.timeit('is_number_try(z)',
    prep_base + prep_try_method), 'seconds')
print()
print('Regex with non-number strings', timeit.timeit('is_number_re(x)',
    prep_base + prep_re_method), 'seconds')
print('Regex with integer strings', timeit.timeit('is_number_re(y)',
    prep_base + prep_re_method), 'seconds')
print('Regex with float strings', timeit.timeit('is_number_re(z)',
    prep_base + prep_re_method), 'seconds')
print()
print('fastnumbers with non-number strings', timeit.timeit('isfloat(x)',
    prep_base + 'from fastnumbers import isfloat'), 'seconds')
print('fastnumbers with integer strings', timeit.timeit('isfloat(y)',
    prep_base + 'from fastnumbers import isfloat'), 'seconds')
print('fastnumbers with float strings', timeit.timeit('isfloat(z)',
    prep_base + 'from fastnumbers import isfloat'), 'seconds')
print()

Try with non-number strings 2.39108395576 seconds
Try with integer strings 0.375686168671 seconds
Try with float strings 0.369210958481 seconds

Regex with non-number strings 0.748660802841 seconds
Regex with integer strings 1.02021503448 seconds
Regex with float strings 1.08564686775 seconds

fastnumbers with non-number strings 0.174362897873 seconds
fastnumbers with integer strings 0.179651021957 seconds
fastnumbers with float strings 0.20222902298 seconds

ご覧のように

  • try: except:は数値入力では高速でしたが、無効な入力では非常に低速でした
  • 入力が無効な場合、正規表現は非常に効率的です。
  • どちらの場合もfastnumbersが勝ちます
15
SethMMorton

私はこれが特に古いことを知っていますが、私はこれを見つける誰にとっても非常に貴重であるかもしれない最も高い投票された答えから抜けている情報をカバーすると私が信じる答えを加えます:

あなたが入力を受け入れる必要がある場合は、以下の方法のそれぞれについて、それらをカウントで接続します。 (0〜255などではなく、整数のボーカル定義を使用していると仮定します。)

x.isdigit() は、xが整数かどうかを調べるのに適しています。

x.replace('-','').isdigit() は、xが負であるかどうかを確認するのに適しています(最初の位置にチェックインします)。

x.replace('.','').isdigit() は、xが10進数であるかどうかを確認するのに適しています。

x.replace(':','').isdigit() は、xが比率であるかどうかを確認するのに適しています。

x.replace('/','',1).isdigit() は、xが小数であるかどうかを確認するのに適しています。

12
Aruthawolf

あなたはUnicode文字列を使用することができます、彼らはあなたが望むことをする方法を持っています:

>>> s = u"345"
>>> s.isnumeric()
True

または

>>> s = "345"
>>> u = unicode(s)
>>> u.isnumeric()
True

http://www.tutorialspoint.com/python/string_isnumeric.htm

http://docs.python.org/2/howto/unicode.html

11
Blackzafiro

Float()はそのためだけのものなので、floatにキャストしてValueErrorをキャッチするのがおそらく最速の方法です。文字列の解析を必要とするもの(regexなど)は、この操作に合わせて調整されていないため、おそらく遅くなります。私の0.02ドル。

10
codelogic

どの方法が最速かを見たかったのです。全体的に最良で最も一貫した結果がcheck_replace関数によって与えられました。最も速い結果はcheck_exception関数によって与えられました、しかし例外が発生しなかった場合だけ - それはそのコードが最も効率的であることを意味します、しかし例外を投げることのオーバーヘッドはかなり大きいです。

成功したキャストをチェックすることが正確な唯一の方法であることに注意してください。例えば、これはcheck_exceptionで動作しますが、他の2つのテスト関数は有効なfloatに対してFalseを返します。

huge_number = float('1e+100')

これがベンチマークコードです。

import time, re, random, string

ITERATIONS = 10000000

class Timer:    
    def __enter__(self):
        self.start = time.clock()
        return self
    def __exit__(self, *args):
        self.end = time.clock()
        self.interval = self.end - self.start

def check_regexp(x):
    return re.compile("^\d*\.?\d*$").match(x) is not None

def check_replace(x):
    return x.replace('.','',1).isdigit()

def check_exception(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

to_check = [check_regexp, check_replace, check_exception]

print('preparing data...')
good_numbers = [
    str(random.random() / random.random()) 
    for x in range(ITERATIONS)]

bad_numbers = ['.' + x for x in good_numbers]

strings = [
    ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(random.randint(1,10)))
    for x in range(ITERATIONS)]

print('running test...')
for func in to_check:
    with Timer() as t:
        for x in good_numbers:
            res = func(x)
    print('%s with good floats: %s' % (func.__name__, t.interval))
    with Timer() as t:
        for x in bad_numbers:
            res = func(x)
    print('%s with bad floats: %s' % (func.__name__, t.interval))
    with Timer() as t:
        for x in strings:
            res = func(x)
    print('%s with strings: %s' % (func.__name__, t.interval))

これが2017年のMacBook Pro 13でのPython 2.7.10の結果です。

check_regexp with good floats: 12.688639
check_regexp with bad floats: 11.624862
check_regexp with strings: 11.349414
check_replace with good floats: 4.419841
check_replace with bad floats: 4.294909
check_replace with strings: 4.086358
check_exception with good floats: 3.276668
check_exception with bad floats: 13.843092
check_exception with strings: 15.786169

これが2017年のMacBook Pro 13でのPython 3.6.5の結果です。

check_regexp with good floats: 13.472906000000009
check_regexp with bad floats: 12.977665000000016
check_regexp with strings: 12.417542999999995
check_replace with good floats: 6.011045999999993
check_replace with bad floats: 4.849356
check_replace with strings: 4.282754000000011
check_exception with good floats: 6.039081999999979
check_exception with bad floats: 9.322753000000006
check_exception with strings: 9.952595000000002

これは2017 MacBook Pro 13でのPyPy 2.7.13の結果です。

check_regexp with good floats: 2.693217
check_regexp with bad floats: 2.744819
check_regexp with strings: 2.532414
check_replace with good floats: 0.604367
check_replace with bad floats: 0.538169
check_replace with strings: 0.598664
check_exception with good floats: 1.944103
check_exception with bad floats: 2.449182
check_exception with strings: 2.200056
9
Ron Reiter

この答えは、文字列が以下のものであることを見つけるための例を含む機能を有するステップバイステップガイドを提供します。

  • 正の整数
  • 正/負 - 整数/ float
  • 数字のチェック中に "NaN"(数字ではない)文字列を破棄する方法?

文字列が正数整数)かどうかをチェック

str.isdigit() を使って、与えられた文字列が正の数整数)かどうかを調べることができます。 

サンプル結果:

# For digit
>>> '1'.isdigit()
True
>>> '1'.isalpha()
False

文字列を正/負 - 整数/浮動小数点数としてチェックします

文字列が負の数数値または浮動小数点数)の場合、str.isdigit()Falseを返します。次に例を示します。

# returns `False` for float
>>> '123.3'.isdigit()
False
# returns `False` for negative number
>>> '-123'.isdigit()
False

負の整数および floatもチェックしたい場合は、カスタム関数を作成して次のようにチェックします。

def is_number(n):
    try:
        float(n)   # Type-casting the string to `float`.
                   # If string is not a valid `float`, 
                   # it'll raise `ValueError` exception
    except ValueError:
        return False
    return True

サンプル実行:

>>> is_number('123')    # positive integer number
True

>>> is_number('123.4')  # positive float number
True

>>> is_number('-123')   # negative integer number
True

>>> is_number('-123.4') # negative `float` number
True

>>> is_number('abc')    # `False` for "some random" string
False

数のチェック中に "NaN"(数ではない)文字列を破棄

Pythonではそれが数値ではないことを表す有効な浮動小数点数であるため、上記の関数は "NAN"(数値ではない)文字列に対してTrueを返します。例えば:

>>> is_number('NaN')
True

番号が "NaN"であるかどうかを確認するには、 math.isnan() を使用します。

>>> import math
>>> nan_num = float('nan')

>>> math.isnan(nan_num)
True

これをチェックするために追加のライブラリをインポートしたくない場合は、==を使用してそれ自身と比較することで単純にチェックすることができます。 False floatがそれ自身と比較されると、Pythonはnanを返します。例えば:

# `nan_num` variable is taken from above example
>>> nan_num == nan_num
False

したがって、上記のfunction is_numberは、"NaN"に対してFalseを返すように更新できます。

def is_number(n):
    is_number = True
    try:
        num = float(n)
        # check for "nan" floats
        is_number = num == num   # or use `math.isnan(num)`
    except ValueError:
        is_number = False
    return is_number

サンプル実行:

>>> is_number('Nan')   # not a number "Nan" string
False

>>> is_number('nan')   # not a number string "nan" with all lower cased
False

>>> is_number('123')   # positive integer
True

>>> is_number('-123')  # negative integer
True

>>> is_number('-1.12') # negative `float`
True

>>> is_number('abc')   # "some random" string
False

PS:数値の種類に応じた各チェックの各操作には、追加のオーバーヘッドが伴います。要件に合ったis_number関数のバージョンを選択してください。

8

あなたは文字列に数字があるとしましょう。

if str.isdigit():
returns TRUE or FALSE 

isdigitドキュメント

そうでなければ、あなたのメソッドは文字列中の数字の出現を見つけるのにとてもうまくいきます。 

7
Clayton

つまり、Nan、無限大、複素数をチェックすると(iではなく、j、つまり1 + 2jで指定されるように見えます)、

def is_number(s):
    try:
        n=str(float(s))
        if n == "nan" or n=="inf" or n=="-inf" : return False
    except ValueError:
        try:
            complex(s) # for complex
        except ValueError:
            return False
    return True
6
a1an

あなたのコードは私にはよく見えます。

おそらく、例外を使用しているためにコードが「不格好」だと思う? Pythonプログラマは、パフォーマンスが低下するため、コードの読みやすさを向上させる場合は、例外を自由に使用する傾向があります。

5
Dubhead

文字列が基本型(float、int、str、bool)にキャストされるかどうかを判断する必要がありました。インターネット上で何も見つけられなかった後、私はこれを作成しました:

def str_to_type (s):
    """ Get possible cast type for a string

    Parameters
    ----------
    s : string

    Returns
    -------
    float,int,str,bool : type
        Depending on what it can be cast to

    """    
    try:                
        f = float(s)        
        if "." not in s:
            return int
        return float
    except ValueError:
        value = s.upper()
        if value == "TRUE" or value == "FALSE":
            return bool
        return type(s)

str_to_type("true") # bool
str_to_type("6.0") # float
str_to_type("6") # int
str_to_type("6abc") # str
str_to_type(u"6abc") # unicode       

あなたはタイプを捉えて使うことができます 

s = "6.0"
type_ = str_to_type(s) # float
f = type_(s) 
4
astrodsg

スピードテストをしました。文字列がlikelyである場合、try/except戦略が可能な限り高速であるとしましょう。 ありそうにない数字になるおよび興味がある整数チェック、テストする価値がある(isdigitと見出し '-') 。浮動小数点数を確認したい場合は、エスケープなしのtry/exceptコードを使用する必要があります。

4
FxIII

入力は次のようになります。

a="50"b=50c=50.1d="50.1"


1 - 一般入力:

この関数の入力はすべてです。

与えられた変数が数値かどうかを調べます。数値ストリングは、オプションの符号、任意の桁数、オプションの小数部、およびオプションの指数部で構成されています。したがって、+ 0123.45e6は有効な数値です。 16進数(例:0xf4c3b00c)およびバイナリ(例:0b10100111001)表記は許可されていません。

is_numeric function

import ast
import numbers              
def is_numeric(obj):
    if isinstance(obj, numbers.Number):
        return True
    Elif isinstance(obj, str):
        nodes = list(ast.walk(ast.parse(obj)))[1:]
        if not isinstance(nodes[0], ast.Expr):
            return False
        if not isinstance(nodes[-1], ast.Num):
            return False
        nodes = nodes[1:-1]
        for i in range(len(nodes)):
            #if used + or - in digit :
            if i % 2 == 0:
                if not isinstance(nodes[i], ast.UnaryOp):
                    return False
            else:
                if not isinstance(nodes[i], (ast.USub, ast.UAdd)):
                    return False
        return True
    else:
        return False

テスト:

>>> is_numeric("54")
True
>>> is_numeric("54.545")
True
>>> is_numeric("0x45")
True

is_float function

与えられた変数がfloatかどうかを調べます。 float文字列は、オプションの符号、任意の桁数、...からなります。

import ast

def is_float(obj):
    if isinstance(obj, float):
        return True
    if isinstance(obj, int):
        return False
    Elif isinstance(obj, str):
        nodes = list(ast.walk(ast.parse(obj)))[1:]
        if not isinstance(nodes[0], ast.Expr):
            return False
        if not isinstance(nodes[-1], ast.Num):
            return False
        if not isinstance(nodes[-1].n, float):
            return False
        nodes = nodes[1:-1]
        for i in range(len(nodes)):
            if i % 2 == 0:
                if not isinstance(nodes[i], ast.UnaryOp):
                    return False
            else:
                if not isinstance(nodes[i], (ast.USub, ast.UAdd)):
                    return False
        return True
    else:
        return False

テスト:

>>> is_float("5.4")
True
>>> is_float("5")
False
>>> is_float(5)
False
>>> is_float("5")
False
>>> is_float("+5.4")
True

ast とは何ですか?


2-あなたが変数contentが String であると確信している場合:

str.isdigit() methodを使用してください。

>>> a=454
>>> a.isdigit()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute 'isdigit'
>>> a="454"
>>> a.isdigit()
True

3 - 数値入力:

int値を検出します。

>>> isinstance("54", int)
False
>>> isinstance(54, int)
True
>>> 

フロートを検出:

>>> isinstance("45.1", float)
False
>>> isinstance(45.1, float)
True
3
user10461621

RyanNは示唆している

NaNとInfに対してFalseを返したい場合は、lineをx = float(s)に変更します。 (x == x)と(x - 1!= x)を返します。これはInfとNaNを除くすべての浮動小数点数に対してTrueを返すはずです。

十分な大きさの浮動小数点数の場合、x-1 == xはtrueを返します。たとえば、2.0**54 - 1 == 2.0**54

3
philh

私はあなたが言及した関数も使用しました、しかしすぐに私は "Nan"、 "Inf"などの文字列とそのバリエーションが数として考慮されることに気付きます。それで私はあなたがあなたの関数の改良版を提案します、それはそれらのタイプの入力で偽を返し、そして "1e3"の変種を失敗しないでしょう:

def is_float(text):
    try:
        float(text)
        # check for nan/infinity etc.
        if text.isalpha():
            return False
        return True
    except ValueError:
        return False
1
mathfac

TrueとFalseよりも有用な値を返すことで、例外の手法を便利な方法で一般化できます。例えば、この関数は文字列に丸引用符を付けますが、数字だけを残します。これは、私がRのためにいくつかの変数を定義するために素早くて汚いフィルタに必要なものです 

import sys

def fix_quotes(s):
    try:
        float(s)
        return s
    except ValueError:
        return '"{0}"'.format(s)

for line in sys.stdin:
    input = line.split()
    print input[0], '<- c(', ','.join(fix_quotes(c) for c in input[1:]), ')'
0
Thruston

これを試して。

 def is_number(var):
    try:
       if var == int(var):
            return True
    except Exception:
        return False
0

ユーザーヘルパー機能:

def if_ok(fn, string):
  try:
    return fn(string)
  except Exception as e:
    return None

それから

if_ok(int, my_str) or if_ok(float, my_str) or if_ok(complex, my_str)
is_number = lambda s: any([if_ok(fn, s) for fn in (int, float, complex)])
0
Samantha Atkins

全体 文字列が数値として表現できるかどうかを知りたい場合は、正規表現を使用します(または、floatを文字列に変換して元の文字列と比較します)。それほど速くはありません。

0
m_eiman

私はあなたの解決策は問題ないと思います。

そうは言っても、私が不当だと思うこれらの答えには多くの正規表現が嫌いです。それは本当にあなたがやろうとしていることによります。元の質問は、どのようにして(文字列が数値(float)として表現できるかどうかを確認する)ことができるかどうかでした(あなたのタイトルのとおり)。おそらく、それが有効であることを確認した後で数値/浮動小数点値を使用したいと思うでしょう。その場合、try/exceptは非常に意味があります。しかし、何らかの理由で string number であることを検証したいだけであれば、正規表現も問題なく動作しますが、正しく取得するのは困難です。私はこれまでのところ大部分の正規表現の答えは、Pythonに関する限り浮動小数点数である整数部分( ".7"のような)がないと文字列を正しく解析しないと思います。そして、小数部分が必要とされない単一の正規表現でチェックするのは少し難しいです。これを示すために2つの正規表現を含めました。

それは「数」が何であるかに関して興味深い質問を提起します。あなたはpythonでfloatとして有効な "inf"を含めますか?それとも「数字」であるがpythonで表現できない数字(例えばfloatの最大値よりも大きい数字など)を含めるか。

数値の解析方法にはあいまいさもあります。たとえば、 " - 20"はどうでしょうか。これは「数」ですか?これは「20」を表すための合法的な方法ですか? Pythonでは、 "var = - 20"を実行して20に設定することはできますが(実際にはこれが式として扱われるためです)、float( " - 20")は機能しません。

とにかく、これ以上の情報がなければ、ここに私はすべての整数と浮動小数点数をカバーすると信じている正規表現です - pythonがそれらを解析するので

# Doesn't properly handle floats missing the integer part, such as ".7"
SIMPLE_FLOAT_REGEXP = re.compile(r'^[-+]?[0-9]+\.?[0-9]+([eE][-+]?[0-9]+)?$')
# Example "-12.34E+56"      # sign (-)
                            #     integer (12)
                            #           mantissa (34)
                            #                    exponent (E+56)

# Should handle all floats
FLOAT_REGEXP = re.compile(r'^[-+]?([0-9]+|[0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?$')
# Example "-12.34E+56"      # sign (-)
                            #     integer (12)
                            #           OR
                            #             int/mantissa (12.34)
                            #                            exponent (E+56)

def is_float(str):
  return True if FLOAT_REGEXP.match(str) else False

テスト値の例

True  <- +42
True  <- +42.42
False <- +42.42.22
True  <- +42.42e22
True  <- +42.42E-22
False <- +42.42e-22.8
True  <- .42
False <- 42nope
0

このコードは、正規表現を使わずに、指数、浮動小数点数、整数を処理します。

return True if str1.lstrip('-').replace('.','',1).isdigit() or float(str1) else False
0
ravi tanwar

これが私の簡単なやり方です。私はいくつかの文字列をループ処理していて、それらが数字であることが判明したらそれらを配列に追加したいとしましょう。

try:
    myvar.append( float(string_to_check) )
except:
    continue

Myvar.apppendを、文字列が数値であることが判明した場合は、その文字列に対して実行する操作に置き換えます。これは、float()操作を使用し、返されたエラーを使用して文字列が数値かどうかを判断することを目的としています。

0
Anil

私はこのスレッドに至るまでの問題、すなわちデータのコレクションを最も直感的な方法で文字列と数値に変換する方法に取り組んでいました。私はオリジナルのコードを読んだ後、私が必要としているのは2つの点で異なることに気付きました。

1 - 文字列が整数を表す場合、整数の結果が欲しい

2 - 数値または文字列の結果をデータ構造に固定したい

だから私はこの派生物を生成するためにオリジナルのコードを修正しました:

def string_or_number(s):
    try:
        z = int(s)
        return z
    except ValueError:
        try:
            z = float(s)
            return z
        except ValueError:
            return s
0
user1508746
import re
def is_number(num):
    pattern = re.compile(r'^[-+]?[-0-9]\d*\.\d*|[-+]?\.?[0-9]\d*$')
    result = pattern.match(num)
    if result:
        return True
    else:
        return False


​>>>: is_number('1')
True

>>>: is_number('111')
True

>>>: is_number('11.1')
True

>>>: is_number('-11.1')
True

>>>: is_number('inf')
False

>>>: is_number('-inf')
False
0
xin.chen