python string to float问题,不要看着这么简单,请入内

yunfeifan 2010-03-08 05:37:31
现在要做一个转换,把string类型转为float
其实float()功能是可以转换的,
但是如果string 为 "00123.456" 或".123456" 或 "0012.3645"的情况先,float()不会抛出异常,而转换成123.456, 0.123456和12.3645等,

我想有没有比较严格的float函数,对于一些错误的书写,直接抛出异常?

我开始用正则写:

def StrToFloat(float_string):
if not re.match(r"^[+-]?(?:0|[1-9]\d*)(\.\d+)?$", float_string):
raise ValueError()
return float(float_string)
会发现1000000需要20秒多的时间,而简单的float 只需要5秒多的时间。
因为我们这个项目的时间、性能要求比较严格,所以有没有什么好的办法,来减少时间的损失,正确的转换或抛出异常?

...全文
22308 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
thy38 2010-04-10
  • 打赏
  • 举报
回复
再举个例子:
>>> 0.1 + 0.1 + 0.1 - 0.3
5.5511151231257827e-17
>>> from decimal import Decimal
>>> def _(x): return Decimal(str(x))
...
>>> _(0.1)+_(0.1)+_(0.1)+_(-0.3)
Decimal('0.0')
thy38 2010-04-10
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 thy38 的回复:]
我对float()忧虑的其实是:
>>> float('.99')
[/Quote]这个问题我发现可以用decimal模块解决:
>>> float('0.98')
0.97999999999999998
>>> import decimal
>>> decimal.Decimal('.98')
Decimal('0.98')
>>> x=float('0.98')
>>> x
0.97999999999999998
>>> x*2
1.96
>>> y=decimal.Decimal('.98')
>>> y*2
Decimal('1.96')
>>>
chaoren_111 2010-03-11
  • 打赏
  • 举报
回复
看了 学习了
iambic 2010-03-11
  • 打赏
  • 举报
回复
先转换成float,如果出错了就是非法的。如果成功了,检查下是不是以00开头,是不是以.开头,是不是.结尾,是不是包含.并且以0结束,如果是,非法。
angel_su 2010-03-11
  • 打赏
  • 举报
回复
[Quote]
判断有效数字 现在还不知道有什么办法能更高效。
[/Quote]

会c扩展的话,自己实现个atof函数,包管快...
gtcoffee 2010-03-11
  • 打赏
  • 举报
回复
def stf(s):
if s.startswith('0') or '.' in s and len(s.split('.')[-1]) > 2:
raise ValueError()
return float(s)


不知這樣行不, 測試過比 re 快很多.....
thy38 2010-03-10
  • 打赏
  • 举报
回复
我有个主意:先把字符a转换成数字x,再把数字x转换成字符b,最后看看a==b ? LZ看看是否可行
yunfeifan 2010-03-09
  • 打赏
  • 举报
回复
Thanks all,

判断有效数字 现在还不知道有什么办法能更高效。
angel_su 2010-03-08
  • 打赏
  • 举报
回复
可以试试用简单字串方法startswith处理,譬如转出<1且>-1间就检查字串开头必要是'0.' '+0.' '-0.', >=1或<=-1的就检查开头是否不能'0' '+0' '-0',这样应该比正则有效率多...
M0521 2010-03-08
  • 打赏
  • 举报
回复
你的问题分步骤解
第一 判定是不是有效的数字
第二 格式化成标准串 比 有效数.有效数 自己定义
第三 输出正确的类型

yunfeifan 2010-03-08
  • 打赏
  • 举报
回复
感谢楼上两位的讲解,但是现在有什么办法来替换掉re吗?

首先我是这样做的
def StrToFloat(float_string):
try:
value = float(float_string)
string = str(value)
if string == float_string or string == (string + '.0'):
return value
else:
raise ValueError()
except ValueError:
print 'Error'

这样的情况如果float_string 是123.4 的情况下效率是最高的,但是如果float_string是一个整形,则效率会慢一些,但是如果float_string是123.400这样的情况话,则没有包含在我的if条件之内,理论上输入的值
123 123.4 123.40应该都属于正常的值,但是0123 0123.4 .123则都不属于正常的值,我现在需要的就是把这样不正常的值给throw出来。

有什么效率更高的办法吗?
FireHell 2010-03-08
  • 打赏
  • 举报
回复
引用 3 楼 thy38 的回复:
我对float()忧虑的其实是:
>>> float('.98')
0.97999999999999998
这样的精度问题。


3楼的兄弟讲得有道理.最近我把IronPython中的数字型重写成了System.Decimal了,可以用于财务计算
CPython的比较麻烦
thy38 2010-03-08
  • 打赏
  • 举报
回复
正则肯定会慢了,Python用的是NFA,会从头到尾扫描一遍。其实我觉得对这个问题没必要用正则了,因为float()函数不抛出异常的情况不多,比如说:起码全部得是数字,只有一个小数点。。。
也就是说,不能算是错误,而只是书写不规范的,才不抛出异常。所以我觉得LZ只要针对这些情况写一个判断函数就可以了,效率应该高不少的。


我对float()忧虑的其实是:
>>> float('.98')
0.97999999999999998
这样的精度问题。
thy38 2010-03-08
  • 打赏
  • 举报
回复
引用 1 楼 firehell 的回复:
最好不要抛异常,抛异常导致的性能损失是可观的.
你说的是静态语言吧,动态语言这个应该不成问题的
FireHell 2010-03-08
  • 打赏
  • 举报
回复
最好不要抛异常,抛异常导致的性能损失是可观的.

37,717

社区成员

发帖
与我相关
我的任务
社区描述
JavaScript,VBScript,AngleScript,ActionScript,Shell,Perl,Ruby,Lua,Tcl,Scala,MaxScript 等脚本语言交流。
社区管理员
  • 脚本语言(Perl/Python)社区
  • IT.BOB
加入社区
  • 近7日
  • 近30日
  • 至今

试试用AI创作助手写篇文章吧