Validate if a given string is numeric.
Note: It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one.
Example:
"0" => true
" 0.1 " => true
"abc" => false
"1 a" => false
"2e10" => true
- 猜猜看我输入的是不是一个数呢?
class Solution:
# @param s, a string
# @return a boolean
def isNumber(self, s):
num_s=s.strip().lower()
(_start, _num1, _e, _signed_e, _null_point, _num_point, _num2, _num3)=range(8)
state=_start
for c in num_s:
if state==_start:
if c=='.':
state=_null_point
elif c=='-' or c=='+':
state=_start
elif ord(c)>=48 and ord(c)<=57:
state=_num1
else:
return False
elif state==_num1:
if c=='.':
state=_num_point
elif c=='e':
state=_e
elif ord(c)>=48 and ord(c)<=57:
state=_num1
else:
return False
elif state==_null_point:
if ord(c)>=48 and ord(c)<=57:
state=_num2
else:
return False
elif state==_num_point:
if ord(c)>=48 and ord(c)<=57:
state=_num2
elif c=='e':
state=_e
else:
return False
elif state==_num2:
if ord(c)>=48 and ord(c)<=57:
state=_num2
elif c=='e':
state=_e
else:
return False
elif state==_e:
if ord(c)>=48 and ord(c)<=57:
state=_num3
elif c=='-' or c=='+':
state=_signed_e
else:
return False
elif state==_signed_e:
if ord(c)>=48 and ord(c)<=57:
state=_num3
else:
return False
elif state==_num3:
if ord(c)>=48 and ord(c)<=57:
state=_num3
else:
return False
if state==_num_point or state==_num1 or state==_num2 or state==_num3:
return True
else:
return False
- 在常规的解法下,完成这个问题是个折磨:
- 扒光洗净之后从头开始判断。
- 把整数、浮点数、科学计数法、正负号的逻辑全走一遍.
- 然后就是如此,这段代码(我拷的)依然存在漏洞,比如“++1”会被识别成正确的。
- 与之相似但是更聪明的方法是进一步将逻辑抽象,构造出完全的逻辑映射:
class Solution(object):
def isNumber(self, s):
"""
:type s: str
:rtype: bool
"""
#define a DFA
state = [{},
{'blank': 1, 'sign': 2, 'digit':3, '.':4},
{'digit':3, '.':4},
{'digit':3, '.':5, 'e':6, 'blank':9},
{'digit':5},
{'digit':5, 'e':6, 'blank':9},
{'sign':7, 'digit':8},
{'digit':8},
{'digit':8, 'blank':9},
{'blank':9}]
currentState = 1
for c in s:
if c >= '0' and c <= '9':
c = 'digit'
if c == ' ':
c = 'blank'
if c in ['+', '-']:
c = 'sign'
if c not in state[currentState].keys():
return False
currentState = state[currentState][c]
if currentState not in [3,5,8,9]:
return False
return True
- 这可以想象成前一种思路的精华形式。
把字符串依次输入,整个判断的逻辑存在于字典列表里。每一个字符后更新一次状态。
如果想不清什么是对的,不妨想想什么是错的,不知道什么是错的,不妨问问编译器:
- 每次程序报错,大多数人都会急匆匆地去看行数,这里给你看个大宝贝:
AttributeError 试图访问一个对象没有的属性
IOError 输入/输出异常
ImportError 无法引入模块或包
IndentationError 代码没有正确对齐
IndexError 索引越界
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 尝试访问一个没有申明的变量
SyntaxError 代码不能编译
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量
ValueError 传入一个调用者不期望的值!!
- 尝试一下
>>> float('0')
0.0
>>> float('++1')
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
float('++1')
ValueError: could not convert string to float: '++1'
>>> float('-1e-2')
-0.01
>>> float('-1e -2')
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
float('-1e -2')
ValueError: could not convert string to float: '-1e -2'
>>> float('shuang')
Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
float('shuang')
ValueError: could not convert string to float: 'shuang'
- 所以说,python还有另外一种可以优雅解决这个问题的方法:
class Solution:
def isNumber(self, s):
"""
:type s: str
:rtype: bool
"""
try:
float(s)
except ValueError:
return False
else:
return True
- 大概意思就是:
- “float,给你看个宝贝”
- “这是什么啊?”
- “别管是什么,我放进去试试”
- “疼疼疼!快拿出去!”
- “看来她不喜欢这个……”