前几天看一个网友提问,如何计算'1+1'这种字符串的值,不能用eval函数.

我仿佛记得以前新手时,对这个问题完全不知道如何下手.

我觉得处理括号实在是太复杂了,多层嵌套括号怎么解析呢?一些多余的括号呢?

而在没有括号的情况下,处理不同运算符之间的优先级又很头疼.

而'**'这种占2个字符的运算符,还有着奇特的优先级规则,x**y**z应先计算y**z,并且如果z后面还跟着**的话,则不能先计算y**z..这是最难的地方!

但是,今天我竟然把它实现了!而且是用最原始的函数实现的,它们是:

str,s.isdigit,s.find,s.count,

dict,float

if,in,and,not

==,>=,+(字符串连接)

float对象的6个方法不计算在内,这是无法避免的基础函数.

而str,float,dict只是起到类型转换或初始化数据的作用.所以真正用到的函数更是少之又少.

可能正是因为如此,我在程序设计上花了很多的心思.我用了非常多的if判断.显得有些难以看懂.而实际上每个分支都对应一种简单的情况.

唯一难的地方在于幂的递归运算(get_rig_rest函数).

这令我非常激动.这让我意识到自己解决复杂问题的能力!

另外应该指出,我的思路来自于前段时间学习Scheme时重写一些基本函数所养成的递归思考的习惯.

同时,Python真的是太方便和强大了,快速的print让测试+修改十分简单,极大提高了大脑解决抽象问题的能力(没有print,也许你要浪费很多笔,纸和时间).

dic={'+':float.__add__,'-':float.__sub__,'*':float.__mul__,'/':float.__floordiv__,'%':float.__mod__,'**':float.__pow__,}

priority=dict((('**',3),('*',2),('/',2),('%',2),('+',1),('-',1)))defprt(opf,p_opf):'幂运算符总是最优先,即使左边也是幂运算符'

if p_opf=='**':returnFalsereturn priority[opf]>=priority[p_opf]defget_val(lef,opf,rig):returnstr(dic[opf](float(lef),float(rig)))defisfloat(s):return s.isdigit() or s=='.'

def get_brace(s,start=0):

pos=s.find(')',start)+1brace=s[:pos]if brace.count('(')==brace.count(')'):returnbrace,s[pos:]returnget_brace(s,pos)def get_rig_rest(s,num=''):'分裂为数字+剩余部分'

'如果数字后是幂运算符,则需要计算该数字的幂,将结果作为数字部分返回'

if s[:2] =='**':

pow_num,rest=get_rig_rest(s[2:])return get_val(num,'**',pow_num),restif s=='' or s[0] indic:returnnum,sif s[0]=='(':

brace,rest=get_brace(s)return ieval(brace[1:-1]),restifisfloat(s[0]):return get_rig_rest(s[1:],num+s[0])def ieval(s,lef='',opf=None,rig=''):if not opf and nots:returnlefif not opf andisfloat(s[0]):return ieval(s[1:],lef+s[0],opf,rig)if not opf and s[0] indic:if s[1]=='*':return ieval(s[2:],lef,'**',rig)return ieval(s[1:],lef,s[0],rig)if not opf and s[0]=='(':

brace,rest=get_brace(s)if notrest:return ieval(brace[1:-1])return ieval(rest,lef+ieval(brace[1:-1]),

opf,rig)if opf and nots:returnget_val(lef,opf,rig)if opf and s[0]=='(':

brace,rest=get_brace(s)if notrest:return get_val(lef,opf,ieval(brace[1:-1]))return ieval(lef+opf+ieval(brace[1:-1])+rest,'',None,'')if opf andisfloat(s[0]):return ieval(s[1:],lef,opf,rig+s[0])if opf and s[0] indic:

number=2 if s[1]=='*' else 1p_opf=s[:number]ifprt(opf,p_opf):return ieval(s,get_val(lef,opf,rig),None,'')

p_rig,p_rest=get_rig_rest(s[number:])return ieval(lef+opf+get_val(rig,p_opf,p_rig)+p_rest,'',None,'')

test=['1+2+3', #常规

'1+2*9', #简单运算符优先级

'1+2*(3+4)', #简单运算符优先级+括号

'4**3**2', #幂运算优先级

'3+2*0.5**(2+2**2)',#多重优先级+括号

'(1+2)*(2+3)', #并列括号

'((9+3)/2)', #嵌套括号

'((1234)-1)', #多余括号

'((1+3**2)*((2%3+(3+3*2**3))*(4-1)*(1+2)+5*6)*4)'] #复杂情形

for x intest:print(ieval(x),'---',eval(x))

结果:

>>>

6.0 --- 6

19.0 --- 19

15.0 --- 15

262144.0 --- 262144

3.03125 --- 3.03125

15.0 --- 15

6.0 --- 6.0

1233.0 --- 1233

11640.0 --- 11640

python中float与eval式一样的吗_用Python最原始的函数模拟eval函数的浮点数运算功能...相关推荐

  1. python中序列类型和数组之间的区别_「Python」序列构成的数组

    一.Python 标准库的序列类型分为: 容器序列: 能够存放不同类型数据的序列(list.tuple.collections.deque). 扁平序列: 只能容纳一种类型的数据(str.bytes. ...

  2. python中表示单一数据的类型被称为_各种Python数据类型的完整列表

    各种Python数据类型的完整列表 如今,Python是最受欢迎的编程语言之一.它允许开发人员将所有精力都放在实现上,而不是将复杂的程序和python中的数据类型用于此目的只是为了简化我们的工作. P ...

  3. python中的装饰器、装饰器模式_浅析Python装饰器以及装饰器模式

    漫谈 如果作为一个Python入门,不了解Python装饰器也没什么,但是如果作为一个中级Python开发人员,如果再不对python装饰器熟稔于心的话,那么可能并没有量变积累到质变. 我以前也看过很 ...

  4. python中init方法的两个下划线_为什么Python中有各种各样的“_”下划线?分别有什么用?...

    刚开始学Python的你一定很疑惑,为什么Python里会出现各种各样的下划线 "_",而且位置都不相同,有时候在名称后面,有时候在前面,有时候还会在数字中间......这些下划线 ...

  5. python中一般使用几个空格表示缩进_为什么Python pep-8强烈建议使用标签上的空格来缩进?...

    为什么Python pep-8强烈建议使用标签上的空格来缩进? 我在Stack Overflow和PEP 8上看到,建议仅在Python程序中使用空格进行缩进. 我能理解一致压痕的必要性,我感到痛苦. ...

  6. python中max()、min()获得最大值与最小值_(Python基础教程之十)Python max()和min()–在列表或数组中查找最大值和最小值...

    使用**max()和min()**方法在可比较元素的集合(例如列表,集合或数组)中查找最大(或最小)项的Python示例. 1. Python max() function max() 该功能用于– ...

  7. python中定义变量有引号和单引号_说说Python 单引号、双引号、三引号的区别?...

    公众号新增加了一个栏目,就是每天给大家解答一道Python常见的面试题,反正每天不贪多,一天一题,正好合适,只希望这个面试栏目,给那些正在准备面试的同学,提供一点点帮助! 小猿会从最基础的面试题开始, ...

  8. python中怎么比较两个列表的大小_在Python中比较两个大小不同的列表

    我有两张不同尺寸的单子.一个有产品名称,另一个有品牌名称(可以是一个词或多个词). 我需要检查产品名称是否有确切的品牌名称(存在于品牌列表中)并提取相同的其他返回空列表. 我在提取匹配的品牌名称时面临 ...

  9. python中的成员运算符是干嘛的_在Python中使用成员运算符的示例

    下表列出了所有Python语言支持的成员运算符. 例如: 试试下面的例子就明白了所有的Python编程语言提供会员运算符: #!/usr/bin/python a = 10 b = 20 list = ...

最新文章

  1. 从 exe.config 读取appSettings 中的配置数据
  2. js hoisting -- 提升 学习笔记
  3. DSP学习 -- 软件开机自启动
  4. 变种 背包问题_【朝夕的ACM笔记】动态规划-背包问题
  5. java sftpv3client_Ganymed SSH-2 for Java系列8之SFTPv3Client说明
  6. 如何向前一个Fragment回传信息?
  7. easyui combobox java_Easyui的combobox实现动态数据级联效果
  8. ssis配置文件优先级_SSIS优先约束概述
  9. 用python画图代码-常用激活函数的python画图代码
  10. 中国资源卫星应用中心免费卫星遥感数据介绍
  11. erp管理系统软件价格
  12. Ionic3/4中如何上传图片(拍照/图片选择)
  13. 论文研究12:DUAL-PATH RNN for audio separation
  14. linux 计算程序运行时间
  15. 手把手教你python实现量价形态选股知乎_【手把手教你】Python实现量价形态选股...
  16. Arduino LCD1602电子时钟
  17. c语言用for或while计算,C语言趣味编程:使用while循环结构计算圆周率pi
  18. 手撸架构,Kafka 面试42问
  19. 只用mysql实现银行转账_基于mysql数据库银行转账功能实现
  20. 虚拟机无端出现 未能将管道连接到虚拟机: 所有的管道范例都在使用中

热门文章

  1. Live2009各产品(如MSN)强迫升级时Server2003系统失败的解决办法
  2. 比特币现金扬声器系列II将领先的比特币一起带来
  3. 火箭队老板成比特币粉丝 旗下豪车经销商接受BTC、BCH支付
  4. 基于比特币现金BCH二层网络能实现区块链2.0以太坊的智能化吗
  5. 盘外招无法击垮比特币现金(BCH)的意志
  6. 小程序无限层级路由方案
  7. Java进阶篇(一)——接口、继承与多态
  8. 更简单的非递归遍历二叉树的方法
  9. 最感动的一首现代诗(转)(修正了一点翻译)
  10. 【Android SOAP】基于第三方开源项目ksoap-android