正剧开始:
星历2016年03月17日 11:46:50, 银河系厄尔斯星球中华帝国江南行省。
[工程师阿伟]正在和[机器小伟]一起研究[分式 小结与复习题]。
<span style="font-size:18px;"> var s = [ '2s(s-2t)/(s+2t)', '1/(x^[2]-y^[2])', '2', '(u^[2]-4uv+4v^[2]-2)/(u^[2]-4v^[2])', 'x^[-6]y^[-9]', '9x^[2]/(y^[6]z^[2])' ];</span>
小伟想看一看这些分式有没有什么规律,于是随意画了几张图:
<span style="font-size:18px;"> //2(1) var result = 0; var array = []; var tmp = []; var colorArray = ['red', 'orange', '#0088FF', 'green', 'cyan', 'blue', '#FF00FF', '#888888', 'black']; var count = 0; for (var s = -10; s < 10; s+=2) { array = []; for (var t = -10; t < 10; t+=2) { result = (s-2*t)/(3*s)*(6*Math.pow(s, 2)/(s+2*t)); array.push(shape.point3D(s, result/20, t)); } tmp = [].concat(array); shape.multiLineDraw(tmp, colorArray[count%8], r); tmp = [].concat(array); shape.pointDraw(tmp, colorArray[count%8], r); count++;</span>
<span style="font-size:18px;"> //2(2) var result = 0; var array = []; var tmp = []; var colorArray = ['red', 'orange', '#0088FF', 'green', 'cyan', 'blue', '#FF00FF', '#888888', 'black']; var count = 0; for (var z = -10; z < 10; z+=2) { array = []; for (var x = -10; x < 10; x+=2) { //x-->x z-->y result = (x-z)/(x+z)+Math.pow(x-z, 2); array.push(shape.point3D(x, result/10-5, z)); } tmp = [].concat(array); shape.multiLineDraw(tmp, colorArray[count%8], r); tmp = [].concat(array); shape.pointDraw(tmp, colorArray[count%8], r); count++; }</span>
<span style="font-size:18px;"> //2(4) var result = 0; var array = []; var tmp = []; var colorArray = ['red', 'orange', '#0088FF', 'green', 'cyan', 'blue', '#FF00FF', '#888888', 'black']; var count = 0; var u , v; for (var z = -10; z < 10; z+=2) { array = []; for (var x = -10; x < 10; x+=2) { //x-->u z-->v u = x; v = z; result = (u-2*v)/(u+2*v)-2/(u*u-4*v*v); array.push(shape.point3D(x, result, z)); } tmp = [].concat(array); shape.multiLineDraw(tmp, colorArray[count%8], r); tmp = [].concat(array); shape.pointDraw(tmp, colorArray[count%8], r); count++; }</span>
<span style="font-size:18px;"> var s = [ '6', 'b^[-1]', '(2x^[2]-12x+16)/(x^[2]-16)', '1/16p^[2]q^[3]r^[-1]+1/(2q)', 'x/(1+x^[2])', '1/(a-b)', '-b/(a+b)', '(x+y)/(x-y)']</span>
小伟为了做这些非常烦的题,专门又给以前的多项式添加了一个计算两个多项式相乘的工具:
<span style="font-size:18px;">### # @usage 两个多项式相乘 # @author mw # @date 2016年03月17日 星期四 14:47:14 # @param 限制很多,但对于项数比较多的一层括号,可省不少麻烦 # @return # ### #多项式s1与s2的乘积,s1, s2都不能有括号 #它们的单项之间用+号或-号相连 #例如a+2b2c3, 2a+4b-c3-1等 #代数字母与次数之间不要有其它符号,不要有乘号和除号 def polymul(s1, s2): if (s1 == '' or s2 == ''): return; #只能有+或-号连接各项,不能有括号,分数要先化成小数 s = s1.replace('-', '+-'); if (s[0] == '+'): s = s[1:]; #各项 terms_1 = s.split('+'); s = s2.replace('-', '+-'); if (s[0] == '+'): s = s[1:]; #各项 terms_2 = s.split('+'); len1 = len(terms_1); len2 = len(terms_2); resultStr = ''; for i in range(len1): for j in range(len2): resultStr += monomul(terms_1[i], terms_2[j])+'+'; lens = len(resultStr); if (resultStr[lens-1] == '+'): resultStr = resultStr[:lens-1]; return resultStr; def monomul(s1, s2): a1 = monoDecomposite(s1); a2 = monoDecomposite(s2); coeff = eval('('+a1[0]+')'+'*'+'('+a2[0]+')'); return str(coeff)+a1[1]+a2[1]; #分解出单项式的系数和其余部分 def monoDecomposite(s): if (s == ''): return ['0', '']; if (s[0].isalpha()): return ['1', s]; lens = len(s); if (s[0] == '-'): if (s[1].isalpha()): return ['-1', s[1:]]; else: index = 1; while (index <= lens-1 and (not s[index].isalpha())): index+=1; return [s[:index], s[index:]]; else: index = 0; while (index <= lens-1 and (not s[index].isalpha())): index+=1; return [s[:index], s[index:]];</span>
<span style="font-size:18px;">### # @usage 单项式相关概念 # @author mw # @date 2016年02月26日 星期五 10:00:14 # @param # @return # ### #单项式 #可以有**, ^号,暂时只能处理代号为一个字母的式子,像x_1, x_n, ...这种还不能处理。 def monomial(s): #原始复本 s0 = s; s = s.replace('**', '^'); s = s.replace('*', ''); if (s.find('+') != -1 or (s.find('-') != -1 and s.find('-')!=0)): print(s0, '不是单项式。'); return []; try: #系数 sign = 1; if s[0] == '-': #负号 sign = -1; s = s[1:]; coefficient = 1; #字符串长度 length = len(s); index = 0; while (not s[index].isalpha()): index+=1; if index >= length: index = length; break; if (index > 0): coefficient = float(s[:index]); if abs(int(coefficient)-coefficient) < 0.001: coefficient = int(coefficient); s = s[index:]; coefficient = sign * coefficient; #系数为0的项,其实就是0 if (coefficient == 0): return []; #print(coefficient, s); length = len(s); array = []; result = []; if (length > 0): index = 0; index2 = 0; name = ''; degree = 0; while index < length: if s[index].isalpha(): if (name != ''): array.append([name, degree]); name = ''; degree = 0; name = s[index]; degree = 1; index += 1; else: index2 = index; tmp = ''; while (not s[index2].isalpha()): index2+=1; if (index2 >= length): index2 = length; break; tmp = s[index:index2]; tmp = tmp.replace('^', ''); degree = float(tmp); if abs(int(degree)-degree) < 0.001: degree = int(degree); index = index2; if (name != ''): array.append([name, degree]); name = ''; degree = 0; #print(array); #所有字母,去除重复的 setA = set(); size = len(array); #单项式的次数 totalDegree = 0; for i in range(size): setA.add(array[i][0]); totalDegree += array[i][1]; listA = list(setA); listA.sort(); size2 = len(listA); result = []; for i in range(size2): #计算每个字母的次数(degree) tmp = 0; for j in range(size): if listA[i] == array[j][0]: tmp += array[j][1]; result.append([listA[i], tmp]); print('单项式{0} 的系数是{1}, 次数是{2},详细是{3}。'.format(\ s0, coefficient, totalDegree, result)); else: totalDegree = 0; if (coefficient != 0): print('单项式{0} 的系数是{1}, 次数是{2},'.format(\ s0, coefficient, 0)); else: print('这个数是0, 暂无规定。'); #返回单项式的次数 return [coefficient, totalDegree, result]; except: print(s0, '有误,无法正确计算。'); ### # @usage 多项式相关概念 # @author mw # @date 2016年02月26日 星期五 10:30:37 # @param 如果有括号,需要先自行去除, # @return # ### def polynomial(s): if (s == ''): return; #预留复本 s0 = s; #只能有+或-号连接各项,不能有括号,分数要先化成小数 s = s.replace('-', '+-'); if (s[0] == '+'): s = s[1:]; #各项 terms = s.split('+'); print('多项式{0} 具有以下的项: {1}\n其中各单项分别是:'.format(s0, terms)); try: size = len(terms); array = []; for i in range(size): #此处也可扩展单项的合法性检查。 if (terms[i] == ''): pass; else: tmp = monomial(terms[i]); #对于返回[]的项,剔除掉 if len(tmp)>0: array.append(tmp); #print(array); size2 = len(array); for i in range(size2): #判断系数是否是0 if array[i][0] == 0: continue; for j in range(i+1, size2): if array[j][0] == 0: continue; else: if (sameTerm(array[i], array[j])): #合并同类项 array[i][0]+=array[j][0]; array[j][0] = 0; result = []; for i in range(size2): #判断系数是否是0 if array[i][0] == 0: continue; else: #保留三位小数 array[i][0] = round(array[i][0], 6); result.append(array[i]); print('合并同类项后详细情况是:', result); sResult = ''; size3 = len(result); if (size3)>0: for i in range(size3): tmp1 = result[i][0]; if (tmp1 >= 0): if (tmp1 != 1): sResult += '+'+str(tmp1); else: sResult += '+'; if (tmp1 < 0): if (tmp1!=-1): sResult += str(tmp1); else: sResult += '-'; tmp2 = result[i][2]; length = len(tmp2); if (length == 0 and abs(tmp1)==1): sResult += '1'; else: for j in range(length): if tmp2[j][1] != 1: sResult += tmp2[j][0]+str(tmp2[j][1]); else: sResult += tmp2[j][0]; if sResult[0] == '+': sResult = sResult[1:]; else: #所有项的系数刚好抵消,导致结果为0 sResult = '0'; print('合并同类项后是 => {0}\n\n'.format(sResult)); except: print(s0, '有误,无法进行多项式操作。'); return; #同类项判断 def sameTerm(a, b): #由于a, b具有以下格式[1, 1, [['v', 1]]] [系数, 次数, 详细元素] if (a[1] == 0 and b[1] == 0): return True; if (a[1] != b[1]): #次数不同 return False; if (len(a[2]) != len(b[2])): #元素个数不同 return False; a1 = list(a[2]); b1 = list(b[2]); a1 = sorted(a1, key=lambda num:num[0]); b1 = sorted(b1, key=lambda num:num[0]); size = len(a1); for i in range(size): if a1[i][0] != b1[i][0] or a1[i][1] != b1[i][1]: return False; return True; ### # @usage 代数式,可以对系数中含计算式的情况进行计算,得出简化后的多项式字符串 # @author mw # @date 2016年02月27日 星期六 09:23:44 # @param # @return # ### #代数式 def algExpr(s): s0 = s; #判断字符串中左右括号是否匹配 if s.count('(') - s.count(')') != 0: print(s, '左右括号数目不匹配,表达式有误。'); return ''; #去除空格 s = s.replace(' ', ''); #存放需要计算的表达式子串 sub = ''; length = len(s); #新字符串 sNew = ''; #括号层次 bracket = 0; result = []; #需要计算的部分,是从每一个单项的开始处,一般只需要计算系数 need = 1; #精度 precision = 6; #遍历字符串s i = 0; while i < length: if (s[i] == '('): bracket+=1; sub += s[i]; elif (s[i] == ')'): bracket -=1; sub += s[i]; elif (s[i].isalpha()): if sub != '': if (sub[-1]=='*'): sub=sub[:-1]; sNew += str(round(eval(sub), precision))+ s[i]; sub = ''; else: sNew += s[i]; #由于字母后面是次数,不需要计算 #need = 0; elif (s[i] == '+' or s[i] == '-'): if (bracket == 0): if sub != '': if (sub[-1]=='*'): sub=sub[:-1]; sNew += str(round(eval(sub), precision))+ s[i]; sub = ''; else: sNew += s[i]; #need = 1; else: sub += s[i]; else: if (need == 1): sub += s[i]; else: sNew += s[i]; i += 1; if sub != '': if (sub[-1]=='*'): sub=sub[:-1]; sNew += str(round(eval(sub), precision)); sub = ''; #print(sNew); return sNew;</span>
<span style="font-size:18px;">if __name__ == '__main__': s1 = polymul('5x+2', 'x+1'); s2 = polymul('-3', 'x2+x'); s = algExpr(s1+'+'+s2); print(polynomial(s)); 多项式5xx+5x+2x+2+-3x2+-3x 具有以下的项: ['5xx', '5x', '2x', '2', '', '-3x2', '', '-3x'] 其中各单项分别是: 单项式5xx 的系数是5, 次数是2,详细是[['x', 2]]。 单项式5x 的系数是5, 次数是1,详细是[['x', 1]]。 单项式2x 的系数是2, 次数是1,详细是[['x', 1]]。 单项式2 的系数是2, 次数是0, 单项式-3x2 的系数是-3, 次数是2,详细是[['x', 2]]。 单项式-3x 的系数是-3, 次数是1,详细是[['x', 1]]。 合并同类项后详细情况是: [[2, 2, [['x', 2]]], [4, 1, [['x', 1]]], [2, 0, []]] 合并同类项后是 => 2x2+4x+2 => x = -1</span>
<span style="font-size:18px;">if __name__ == '__main__': s1 = polymul('2x', '2x+5'); s2 = polymul('-2', '2x-5'); s3 = polymul('-2x+5', '2x+5'); s = algExpr(s1+'+'+s2+'+'+s3); print(polynomial(s)); >>> 多项式4xx+10x+-4x+10+-4xx+-10x+10x+25 具有以下的项: ['4xx', '10x', '', '-4x', '10', '', '-4xx', '', '-10x', '10x', '25'] 其中各单项分别是: 单项式4xx 的系数是4, 次数是2,详细是[['x', 2]]。 单项式10x 的系数是10, 次数是1,详细是[['x', 1]]。 单项式-4x 的系数是-4, 次数是1,详细是[['x', 1]]。 单项式10 的系数是10, 次数是0, 单项式-4xx 的系数是-4, 次数是2,详细是[['x', 2]]。 单项式-10x 的系数是-10, 次数是1,详细是[['x', 1]]。 单项式10x 的系数是10, 次数是1,详细是[['x', 1]]。 单项式25 的系数是25, 次数是0, 合并同类项后详细情况是: [[6, 1, [['x', 1]]], [35, 0, []]] 合并同类项后是 => 6x+35 None >>> 2*(-35/6)/(2*(-35/6)-5)-2/(2*(-35/6)+5) 1.0 </span>
好吧,这些烦琐的分式计算,还是留给需要计算它们的小朋友吧。
小伟在这里总结一下工具的使用:
<span style="font-size:18px;">if __name__ == '__main__': #可计算多项式的乘法,但不能有括号 s1 = polymul('x+y+z+u+v', 'x+y+z-u-v'); print(polynomial(s1)); #指数上有负号时会出错,这个可以解决,但是会要求更复杂的写法 s2 = '(5*2*3-8-6)a(-2)a2' print(polynomial(algExpr(s2))); #对于正指数会很方便 s3 = '(5*2*3-8-6)a2abcdef2g+s(2*3)d3-28.66gdf-3'; print(polynomial(algExpr(s3))); </span>
<span style="font-size:18px;">>>> 多项式1xx+1xy+1xz+-1xu+-1xv+1yx+1yy+1yz+-1yu+-1yv+1zx+1zy+1zz+-1zu+-1zv+1ux+1uy+1uz+-1uu+-1uv+1vx+1vy+1vz+-1vu+-1vv 具有以下的项: ['1xx', '1xy', '1xz', '', '-1xu', '', '-1xv', '1yx', '1yy', '1yz', '', '-1yu', '', '-1yv', '1zx', '1zy', '1zz', '', '-1zu', '', '-1zv', '1ux', '1uy', '1uz', '', '-1uu', '', '-1uv', '1vx', '1vy', '1vz', '', '-1vu', '', '-1vv'] 其中各单项分别是: 单项式1xx 的系数是1, 次数是2,详细是[['x', 2]]。 单项式1xy 的系数是1, 次数是2,详细是[['x', 1], ['y', 1]]。 单项式1xz 的系数是1, 次数是2,详细是[['x', 1], ['z', 1]]。 单项式-1xu 的系数是-1, 次数是2,详细是[['u', 1], ['x', 1]]。 单项式-1xv 的系数是-1, 次数是2,详细是[['v', 1], ['x', 1]]。 单项式1yx 的系数是1, 次数是2,详细是[['x', 1], ['y', 1]]。 单项式1yy 的系数是1, 次数是2,详细是[['y', 2]]。 单项式1yz 的系数是1, 次数是2,详细是[['y', 1], ['z', 1]]。 单项式-1yu 的系数是-1, 次数是2,详细是[['u', 1], ['y', 1]]。 单项式-1yv 的系数是-1, 次数是2,详细是[['v', 1], ['y', 1]]。 单项式1zx 的系数是1, 次数是2,详细是[['x', 1], ['z', 1]]。 单项式1zy 的系数是1, 次数是2,详细是[['y', 1], ['z', 1]]。 单项式1zz 的系数是1, 次数是2,详细是[['z', 2]]。 单项式-1zu 的系数是-1, 次数是2,详细是[['u', 1], ['z', 1]]。 单项式-1zv 的系数是-1, 次数是2,详细是[['v', 1], ['z', 1]]。 单项式1ux 的系数是1, 次数是2,详细是[['u', 1], ['x', 1]]。 单项式1uy 的系数是1, 次数是2,详细是[['u', 1], ['y', 1]]。 单项式1uz 的系数是1, 次数是2,详细是[['u', 1], ['z', 1]]。 单项式-1uu 的系数是-1, 次数是2,详细是[['u', 2]]。 单项式-1uv 的系数是-1, 次数是2,详细是[['u', 1], ['v', 1]]。 单项式1vx 的系数是1, 次数是2,详细是[['v', 1], ['x', 1]]。 单项式1vy 的系数是1, 次数是2,详细是[['v', 1], ['y', 1]]。 单项式1vz 的系数是1, 次数是2,详细是[['v', 1], ['z', 1]]。 单项式-1vu 的系数是-1, 次数是2,详细是[['u', 1], ['v', 1]]。 单项式-1vv 的系数是-1, 次数是2,详细是[['v', 2]]。 合并同类项后详细情况是: [[1, 2, [['x', 2]]], [2, 2, [['x', 1], ['y', 1]]], [2, 2, [['x', 1], ['z', 1]]], [1, 2, [['y', 2]]], [2, 2, [['y', 1], ['z', 1]]], [1, 2, [['z', 2]]], [-1, 2, [['u', 2]]], [-2, 2, [['u', 1], ['v', 1]]], [-1, 2, [['v', 2]]]] 合并同类项后是 => x2+2xy+2xz+y2+2yz+z2-u2-2uv-v2 None 多项式16a-2a2 具有以下的项: ['16a', '-2a2'] 其中各单项分别是: 单项式16a 的系数是16, 次数是1,详细是[['a', 1]]。 单项式-2a2 的系数是-2, 次数是2,详细是[['a', 2]]。 合并同类项后详细情况是: [[16, 1, [['a', 1]]], [-2, 2, [['a', 2]]]] 合并同类项后是 => 16a-2a2 None 多项式16a2abcdef2g+s6d3-28.66gdf-3 具有以下的项: ['16a2abcdef2g', 's6d3', '-28.66gdf', '-3'] 其中各单项分别是: 单项式16a2abcdef2g 的系数是16, 次数是10,详细是[['a', 3], ['b', 1], ['c', 1], ['d', 1], ['e', 1], ['f', 2], ['g', 1]]。 单项式s6d3 的系数是1, 次数是9,详细是[['d', 3], ['s', 6]]。 单项式-28.66gdf 的系数是-28.66, 次数是3,详细是[['d', 1], ['f', 1], ['g', 1]]。 单项式-3 的系数是-3, 次数是0, 合并同类项后详细情况是: [[16, 10, [['a', 3], ['b', 1], ['c', 1], ['d', 1], ['e', 1], ['f', 2], ['g', 1]]], [1, 9, [['d', 3], ['s', 6]]], [-28.66, 3, [['d', 1], ['f', 1], ['g', 1]]], [-3, 0, []]] 合并同类项后是 => 16a3bcdef2g+d3s6-28.66dfg-3 None >>> </span>
本节到此结束,欲知后事如何,请看下回分解。