[机器小伟]在[工程师阿伟]的陪同下进入了筑基中期的修炼,
这次要修炼的目标是[分式 小结与复习题]。
正剧开始:
星历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>
x = -1时分母为0了,所以这个方程无解!
<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>
验算通过,这个解是x = -35/6
好吧,这些烦琐的分式计算,还是留给需要计算它们的小朋友吧。
小伟在这里总结一下工具的使用:
<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>
反正是烦琐透了。还不如用草稿本划同类项来得快呢。
本节到此结束,欲知后事如何,请看下回分解。