问题描述
我不是程序员,所以请放轻松!我有一个由 4 个线性方程和 4 个未知数组成的系统,我认为我可以使用 python 相对轻松地解决这些问题。然而,我的方程不是“5x+2y+zw=0”形式的,而是我有代数常数 c_i,我不知道它的显式数值,例如“c_1 x + c_2 y + c_3 z+ c_4w=c_5”将是一个我的四个方程。那么是否存在根据 c_i 给出 x,y,z,w 答案的求解器?
解决方法
Numpy 有一个函数可以解决这个问题:numpy.linalg.solve
要构建矩阵,我们首先需要消化字符串,将其转换为系数和解的数组。
找数字
首先我们需要编写一个函数,它接受一个像 "c_1 3" 这样的字符串并返回数字 3.0。根据您在输入字符串中所需的格式,您可以遍历此数组中的所有字符并在找到非数字字符时停止,或者您可以简单地拆分空格并解析第二个字符串。以下是两种解决方案:
def find_number(sub_expr):
"""
Finds the number from the format
number*string or numberstring.
Example:
3x -> 3
4*x -> 4
"""
num_str = str()
for char in sub_expr:
if char.isdigit():
num_str += char
else:
break
return float(num_str)
或更简单的解决方案
def find_number(sub_expr):
"""
Returns the number from the format "string number"
"""
return float(sub_expr.split()[1])
注意:查看编辑
获取矩阵
现在我们可以使用它来将每个表达式分成两部分:解和由“=”组成的方程。然后方程被“+”分割成子表达式这样我们就可以把字符串“3x+4y = 3”变成
sub_expressions = ["3x","4y"]
solution_string = "3"
然后需要将每个子表达式输入到我们的 find_numbers
函数中。最终结果可以附加到系数和解矩阵:
def get_matrices(expressions):
"""
Returns coefficient_matrix and solutions from array of string-expressions.
"""
coefficient_matrix = list()
solutions = list()
last_len = -1
for expression in expressions:
# Note: In this solution all coefficients must be explicitely noted and must always be in the same order.
# Could be solved with dicts but is probably overengineered.
if not "=" in expression:
print(f"Invalid expression {expression}. Missing \"=\"")
return False
try:
c_string,s_string = expression.split("=")
c_strings = c_string.split("+")
solutions.append(float(s_string))
current_len = len(c_strings)
if last_len != -1 and current_len != last_len:
print(f"The expression {expression} has a mismatching number of coefficients")
return False
last_len = current_len
coefficients = list()
for c_string in c_strings:
coefficients.append(find_number(c_string))
coefficient_matrix.append(coefficients)
except Exception as e:
print(f"An unexpected Runtime Error occured at {coefficient}")
print(e)
exit()
return coefficient_matrix,solutions
现在让我们编写一个简单的 main 函数来测试这段代码:
# This is not the code you want to copy-paste
# Look further down.
from sys import argv as args
def main():
expressions = args[1:]
matrix,solutions = get_matrices(expressions)
for row in matrix:
print(row)
print("")
print(solutions)
if __name__ == "__main__":
main()
让我们在控制台中运行程序!
user:$ python3 solve.py 2x+3y=4 3x+3y=2
[2.0,3.0]
[3.0,3.0]
[4.0,2.0]
您可以看到程序正确识别了我们所有的号码
再次:使用适合您的格式的 find_number 函数
拼凑起来
这些矩阵现在只需要直接注入 numpy 函数即可:
# This is the main you want
from sys import argv as args
from numpy.linalg import solve as solve_linalg
def main():
expressions = args[1:]
matrix,solutions = get_matrices(expressions)
coefficients = solve_linalg(matrix,solutions)
print(coefficients)
# This bit needs to be at the very bottom of your code to load all functions first.
# You could just paste the main-code here,but this is considered best-practice
if __name__ == '__main__':
main()
现在让我们测试一下:
$ python3 solve.py x*2+y*4+z*0=20 x*1+y*1+z*-1=3 x*2+y*2+z*-3=3
[2. 4. 3.]
如您所见,该程序现在为我们解决了这些功能。
出于好奇:数学作业?这感觉就像数学作业。
编辑:出于纯粹的运气,在所有测试中都解决了拼写错误“c_string”而不是“c_strings”。
编辑 2:经过进一步检查,我建议用“*”分割子表达式:
def find_number(sub_expr):
"""
Returns the number from the format "string number"
"""
return float(sub_expr.split("*")[1])
这导致相当可读的输入字符串