python - 当涉及非常大的计算时,如何编写程序以显示“太大的结果”?
问题描述
我尝试在图形计算器中计算 32**(32**32),但程序挂起。如何像字符串一样显示“太大的结果”而不是挂起?
我使用了以下功能。
def result(text):
global backend, frontend, backend_list, frontend_list
try:
backend_list.append(str(eval(backend)))
backend=backend_list[-1]
frontend_list.append(str(round(eval(backend),5)))
frontend=frontend_list[-1]
backend_list.clear()
backend_list.append(backend)
frontend_list.clear()
frontend_list.append(frontend)
text.delete(1.0, END)
text.insert(INSERT, frontend)
except ZeroDivisionError:
backend=frontend=""
text.delete(1.0, END)
text.insert(INSERT, "not defined")
except TypeError:
backend=frontend=""
text.delete(1.0, END)
text.insert(INSERT, "type error: presumably\ncomplex number or\nmissing operators")
except:
text.delete(1.0, END)
text.insert(INSERT, "error")
解决方案
python 这样做的问题是 python 在技术上没有整数的大小限制。最终,您的计算机将在尝试计算时耗尽内存,但这需要一段时间,并且计算机将挂起,直到它完成为止。
与整数不同,浮点数有大小限制。如果需要,您可以将参数转换为浮点数并依靠内置的浮点行为为您完成工作:
try:
eval('float(32) ** 32 ** 32')
except OverflowError:
print("Result too large")
问题在于您依赖eval()
,这使您无法控制。如果您希望您的计算器真正灵活,您必须自己解码和解释表达式。ast
或 'Abstract Syntax Tree'是最好的方法,您可以使用 和 的组合来逐个遍历操作数并根据需要对其进行评估ast.parse(your_input)
。ast.walk(result_of_parse)
这会很复杂,您需要仔细考虑如何实现它,但一个简单的解决方案可能是遍历树并将所有常量转换为浮点数,如果它们还没有的话:
import ast
...
def eval_ast(expr='32 ** 32 ** 32'):
# decompose into parsed elements
# if entered normally, expr() will be a hierarchy of AST objects. The top few
# are not useful to us:
# ast.Module (has attribute .body containing a list of the next level)
# ast.Expr (has attribute .value containing the next level)
# so we attempt to ignore them.
expr_obj = ast.Expression(ast.parse(expr).body[0].value)
# walk through the nodes in the AST and convert integers to floats
for node in ast.walk(expr_obj):
if isinstance(node, ast.Constant):
node.value = float(node.value)
# recompose back into an evaluatable expression
expr_eval = ast.fix_missing_locations(expr_obj)
exe = compile(expr_eval, filename="<string>", mode="eval")
return eval(exe)
如所写,这将引发“结果太大”错误。如果使用不同的表达式调用,不会溢出,它将正确返回结果:
>>> eval_ast('32 ** 32 ** 32')
Traceback (most recent call last):
...
OverflowError: (34, 'Result too large')
>>> eval_ast('2 ** 32')
4294967296.0
您可以自定义它并根据需要将其集成到您的计算器中。如果您需要更精确或更精细的控制,手动遍历 AST 表达式并自己评估每个步骤可能对您更有用。
推荐阅读
- vhdl - 用于记录分配的 VHDL 逻辑向量
- ios - 在 iOS 中,如果固定的 SSL 证书过期,我需要重新提交应用程序吗?
- python - 生成器理解忽略类范围
- node.js - 在 npm 开发构建中反应应用程序部署错误
- node.js - 集成测试 node.js socket.io 服务器
- c# - Docker for C# core (linux type) 行为 - 与镜像构建相关
- angular - Angular 7 CLI 以编程方式
- html - 显示当前 div 侧边栏
- codenameone - QRScanner 使用前置摄像头
- django - Django CreateView - created_by,modified_by mixin 不起作用