[从头学数学] 第221节 带着计算机去高考(十三)

剧情提要:
[机器小伟]在[工程师阿伟]的陪同下进入了[九转金丹]之第八转的修炼。设想一个场景:
如果允许你带一台不连网的计算机去参加高考,你会放弃选择一个手拿计算器和草稿本吗
?阿伟决定和小伟来尝试一下用计算机算高考题会是怎样的感觉。

正剧开始:

星历2016年05月25日 10:40:52, 银河系厄尔斯星球中华帝国江南行省。
[工程师阿伟]正在和[机器小伟]一起做着2012年的江苏省数学高考题]。


这就是传说中的厄尔斯星球末日那一年的考题,这一年的考题难度绝对是在5.5环以上。

[从头学数学] 第221节 带着计算机去高考(十三)_第1张图片


可以从上表中看到,由于连续三年难度达到5.5环以上,说明江苏的考卷已经是铁了心要走残酷模式了,

不再像以前那样容易三年难一年,正弦曲线式的遮遮掩掩的难。


这张卷子的素材刚好是答案和题粘在一起,而阿伟又刚好懒得去把它分开,毕竟何必和自己过不去呢,

高考离阿伟已经很遥远了,咱只是观光一下而已啦。




[从头学数学] 第221节 带着计算机去高考(十三)_第2张图片


[从头学数学] 第221节 带着计算机去高考(十三)_第3张图片


[从头学数学] 第221节 带着计算机去高考(十三)_第4张图片




[从头学数学] 第221节 带着计算机去高考(十三)_第5张图片


[从头学数学] 第221节 带着计算机去高考(十三)_第6张图片


[从头学数学] 第221节 带着计算机去高考(十三)_第7张图片






[从头学数学] 第221节 带着计算机去高考(十三)_第8张图片


[从头学数学] 第221节 带着计算机去高考(十三)_第9张图片


[从头学数学] 第221节 带着计算机去高考(十三)_第10张图片




[从头学数学] 第221节 带着计算机去高考(十三)_第11张图片


[从头学数学] 第221节 带着计算机去高考(十三)_第12张图片


[从头学数学] 第221节 带着计算机去高考(十三)_第13张图片


[从头学数学] 第221节 带着计算机去高考(十三)_第14张图片


[从头学数学] 第221节 带着计算机去高考(十三)_第15张图片


[从头学数学] 第221节 带着计算机去高考(十三)_第16张图片


[从头学数学] 第221节 带着计算机去高考(十三)_第17张图片



<span style="font-size:18px;">#题22B
def tmp22B():
    A_ = [[-1/4, 3/4], [1/2, -1/2]];
    A = np.linalg.inv(A_);
    print(A);
    #求特征值
    eig = np.linalg.eig(A);
    print(eig);
    
	
>>> 
[[ 2.  3.]
 [ 2.  1.]]
(array([ 4., -1.]), array([[ 0.83205029, -0.70710678],
       [ 0.5547002 ,  0.70710678]]))
	   </span>

[从头学数学] 第221节 带着计算机去高考(十三)_第18张图片











卷子贴完了,但阿伟这次主要是想做一个测试,测试这样一个题:



这个图如下:


[从头学数学] 第221节 带着计算机去高考(十三)_第19张图片


怎样解呢?

[从头学数学] 第221节 带着计算机去高考(十三)_第20张图片




<span style="font-size:18px;">#测试
def tmp():
    #先化出x^[2]/4
    x = alg.strformat(['y^[-1]', '-1']);
    x2 = alg.strcombine(alg.strpow_n(x, 2));
    print(x2);

    x2 = alg.strscale(x2, '1/4');
    print('step1: ', x2);

    
    expr = alg.strcombine(alg.stradd(x2, alg.strformat(['0.5y^[2]', '-1'])));
    print('step2: ', expr);

    solve = StringAlgSolve();
    poly_y = solve.coefPoly(expr, 'y');
    print('step3: ', poly_y);

    roots = np.roots(poly_y);
    print('step4: ', roots);
    
    points = [];
    for i in range(len(roots)):
        real = roots[i].real;
        abs_ = abs(roots[i]);
        #实数根
        if abs(real-abs_) < 0.001:
            y = roots[i];
            
            points.append([1/y-1, y]);

    print('step6: ', points);



>>> 
['(1)*y^[-2]', '(-2)*y^[-1]', '(1)']
step1:  ['(0.25)*y^[-2]', '(-0.5)*y^[-1]', '(0.25)']
step2:  ['(0.25)*y^[-2]', '(-0.5)*y^[-1]', '(-0.75)', '(0.5)*y^[2]']
step3:  [0.5, '0', -0.75, -0.5, 0.25]
step4:  [ 1.39972286+0.j         -0.86985159+0.54226114j -0.86985159-0.54226114j
  0.33998033+0.j        ]
step6:  [[(-0.28557285734613158+0j), (1.399722855272995+0j)], [(1.9413466331266509+0j), (0.33998033034855202+0j)]]
</span>

<span style="font-size:18px;">	if (1) {      
        var r = 20;            
        config.setSector(1,1,1,1);              
        config.graphPaper2D(0, 0, r);            
        config.axis2D(0, 0,180);              
                
        //坐标轴设定        
        var scaleX = 2*r, scaleY = 2*r;          
        var spaceX = 0.4, spaceY = 0.4;           
        var xS = -10, xE = 10;          
        var yS = -10, yE = 10;          
        config.axisSpacing(xS, xE, spaceX, scaleX, 'X');            
        config.axisSpacing(yS, yE, spaceY, scaleY, 'Y');            
                    
        var transform = new Transform();            
        //存放函数图像上的点        
        var a = [], b = [], c = [], d = [];          
                  
        //需要显示的函数说明    
                    //希腊字母表(存此用于Ctrl C/V  
            //ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ  
            //αβγδεζηθικλμνξοπρστυφχψω  
        var f1 = 'x^[2]/4+y^[2]/2 = 1', f2 = 'y = 1/(1+x)', f3 = '', f4 = '';        
            
  
        //函数描点    
        //参数方程  
        var x, y;  
        var pointA = [];  
          
        for (var thita = 0; thita < Math.PI*2; thita +=Math.PI/48) {  
			x = 2*Math.cos(thita);
            a.push([2*Math.cos(thita), 1.414*Math.sin(thita)]);  
			b.push([x, 1/(1+x)]);
        }  
          
                  
        //存放临时数组        
        var tmp = [];        
                  
        //显示变换        
        if (a.length > 0) {        
            a = transform.scale(transform.translate(a, 0, 0), scaleX/spaceX, scaleY/spaceY);         
            //函数1        
            tmp = [].concat(a);            
            shape.pointDraw(tmp, 'red');            
            tmp = [].concat(a);            
            shape.multiLineDraw(tmp, 'pink');          
                      
            plot.setFillStyle('red');        
            plot.fillText(f1, 100, -120, 200);          
        } 

		//显示变换        
        if (b.length > 0) {        
            b = transform.scale(transform.translate(b, 0, 0), scaleX/spaceX, scaleY/spaceY);         
            //函数1        
            tmp = [].concat(b);            
            shape.pointDraw(tmp, 'blue');            
            tmp = [].concat(b);            
            shape.multiLineDraw(tmp, '#0088FF');          
                      
            plot.setFillStyle('blue');        
            plot.fillText(f2, 100, -150, 200);          
        }  
  
          
    }
	</span>

<span style="font-size:18px;">	//测试
	if (1) {
		var mathText = new MathText();
		
		//希腊字母表(存此用于Ctrl C/V
			//ΑΒΓΔΕΖΗ ΘΙΚΛΜΝΞ ΟΠΡ ΣΤΥ ΦΧΨ Ω
			//αβγδεζη θικλμνξ οπρ στυ φχψ ω
			
		//希腊大小写字母
		var Gc = 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ';
		var Gs = 'αβγδεζηθικλμνξοπρστυφχψω';
		
		
		
		var s = [
			/*
			'测试',
			'y = 1/(x+1)    _[(1)]',
			'x^[2]/4+y^[2]/2 = 1  _[(2)]',
			'求交点',
			
			
			'由_[(1)]得 x = y^[-1]-1, 代入_[(2)]式',
			'step1: 先化出x^[2]/4',
			'step2: 把_[(2)]整理完全',
			'step3: 把step2所得表达式转入参数y的幂次多项式',
			'step4: 求幂次多项式的根',
			
			'step5: 上一步解得y=1.4 或 0.34,代入求x',
			'step6:得两个点: [-0.286, 1.4], [1.94, 0.34]',
			'step7:画图验证',
			
			
			'这个题是可以这样解决了,大家可见下面的解答。',*/
			
			
			'那么如果上面 _[(1)]式是 y = 1/(x+1)+1呢,',
			'这就不是简单多项式了。这种还好办,',
			'可以作一个y-1 = y_[2]的变换,只是麻烦点。',
			'那如果是两个二次式联立呢?或者高于二次呢?',
			'这个[机器小伟]现在是解不了的了。',
			'是不是除了用数值计算方法以外别无选择?',
			'民间有高人,阿伟很期待。'		
			
		];
		
		var x =40, y=40;
		var r1 = 40;
				
		var len = s.length;
		for (var i = 0; i < len; i++) {
		
			if (s[i] == '') {
				if (x < 100) {
					x += 300;
					y-=r1*3;
				}
				else {
					x = 20;
					y += r1;
				}
			}
			else {			
				mathText.print(s[i], x, y, 'red', '|');
				y+=r1;
			}
		}		
	
	}
	</span>

[从头学数学] 第221节 带着计算机去高考(十三)_第21张图片

这里贴出相关的工具,作为大家的一个起点吧,

很多以前贴过,但是改了里面几个小Bug:

<span style="font-size:18px;">###
# @usage   代数式字符串的运算
# @author  mw
# @date    2016年05月17日  星期二  16:48:56 
# @param
# @return
#
###

#计算代数式用, 传入的是单项式,返回coef*expr的形式
def strmono(s):
    #'x', '-x', '2x', '-2x', '-2x^[2]', '3x_[2]^[3]', '-3x_[2]^[3]'
    stmp = s;
    size = len(stmp);
    alphaIndex = 0;
    signIndex = 0;
    
    for i in range(size):
        if (stmp[i].isalpha()):
            alphaIndex = i;
            break;
        if (i >= size-1):
            alphaIndex = i+1;


    
    if (stmp[0] == '-'):
        signIndex = 1;
        if (signIndex >= alphaIndex):
            return monoformat('(-1)*'+stmp[alphaIndex:]);
        else:
            if alphaIndex >= size:
                return monoformat('(-'+stmp[signIndex:alphaIndex]+')');
            return monoformat('(-'+stmp[signIndex:alphaIndex]+')*'+stmp[alphaIndex:]);
    elif (stmp[0] == '('):
        #已经格式化的情况,这种情况输入时是(coef)*expr
        return monoformat(stmp);
    else:
        signIndex = 0;        
        if (signIndex >= alphaIndex):
            return monoformat('(1)*'+stmp[alphaIndex:]);
        else:
            if alphaIndex >= size:
                return monoformat('('+stmp[signIndex:alphaIndex]+')');
            return monoformat('('+stmp[signIndex:alphaIndex]+')*'+stmp[alphaIndex:]);

#计算两个单项式的乘积
def strmul(mono1, mono2):
    #这个处理是保证每个单项式统一格式(coef)*expr
    '''
    if (mono1[0] != '(' or mono2[0] != '('):
        #如果没有规格化,那么就做一下
        mono1 = strmono(mono1);
        mono2 = strmono(mono2);
    '''
    stmp1 = mono1;
    stmp2 = mono2;

    #乘号的位置
    signIndex1 = stmp1.find('*');
    signIndex2 = stmp2.find('*');
    if (signIndex1 == -1):
        coef1 = stmp1;
        expr1 = '';
    else:
        coef1 = stmp1[:signIndex1];
        expr1 = stmp1[signIndex1+1:];

    if (signIndex2 == -1):
        coef2 = stmp2;
        expr2 = '';
    else:
        coef2 = stmp2[:signIndex2];
        expr2 = stmp2[signIndex2+1:];
        
    coef = coef1+'*'+coef2;
    
    if (signIndex1 == -1 or signIndex2 == -1):
        expr = expr1+expr2;
    else:
        expr = expr1+'*'+expr2;

    if (expr == ''):
        return '('+str(round(eval(coef), 6))+')';
    return '('+str(round(eval(coef), 6))+')*'+expr;
    
#计算两个单项式的商
def strdiv(s1, s2):
    #这个处理是保证每个单项式统一格式(coef)*expr
    stmp1 = strmono(s1);
    stmp2 = strmono(s2);

    #乘号的位置
    signIndex1 = stmp1.find('*');
    signIndex2 = stmp2.find('*');
    if (signIndex1 == -1):
        coef1 = stmp1;
        expr1 = '';
    else:
        coef1 = stmp1[:signIndex1];
        expr1 = stmp1[signIndex1+1:];

    if (signIndex2 == -1):
        coef2 = stmp2;
        expr2 = '';
    else:
        coef2 = stmp2[:signIndex2];
        expr2 = stmp2[signIndex2+1:];
        
    coef = coef1+'/'+coef2;
    
    if (signIndex1 == -1 and signIndex2 != -1):
        expr = '('+expr2+')^[-1]';
    elif (signIndex1 == -1 or signIndex2 == -1):
        expr = expr1+expr2;
    else:
        expr = expr1+'/'+expr2;

    if (expr == ''):
        return '('+str(round(eval(coef), 6))+')';
    return '('+str(round(eval(coef), 6))+')*'+expr;

#把多项式中每一项都乘系数
def strscale(array, scale):
    scale = '('+str(scale)+')';
    for i in range(len(array)):
        s = array[i];

        for j in range(len(s)):
            if (s[j].isdigit()):
                index = j;
                break;
        lbracket = s.find('(');
        rbracket = s.find(')', lbracket);
        
        coef = s[lbracket:index]+scale+'*'+s[index:rbracket+1];
        coef = '('+str(eval(coef))+')';
        
        array[i] = coef+s[rbracket+1:];

    return array;
        


#找一个字符串中所有待查找子串的位置,返回位置阵列
def findall(string, sub):
    size = len(string);
    index = [];

    cur = string.find(sub);
    index.append(cur)
    
    while (index[-1] != -1):        
        cur = string.find(sub, index[-1]+1);
        index.append(cur);   

    return index;

#计算单项式的乘方, s^n
def strpow(s, n):
    stmp = strmono(s);
    signIndex = stmp.find('*');
    if (signIndex == -1):
        coef = stmp+'**'+str(n);
        expr = '';
        return '('+str(round(eval(coef), 6))+')';
    else:
        coef = stmp[:signIndex]+'**'+str(n);
        expr = '('+stmp[signIndex+1:]+')^['+str(n)+']';

    return '('+str(round(eval(coef), 6))+')*'+expr;

#计算代数式用,传入的两个阵列都具有['s1', 's2', ..., 'sn']这样的格式
def strdot(array1, array2):
    size1 = len(array1);
    size2 = len(array2);
    result = [];
    
    for i in range(size1):
        for j in range(size2):
            result.append(strmul(array1[i], array2[j]));

    return result;


#把格式化后的单项式分解成[coef, expr]对组的形式
def explodemono(mono):
    stmp = mono;

    #乘号的位置
    signIndex = stmp.find('*');
    if (signIndex == -1):
        coef = stmp;
        expr = '';
    else:
        coef = stmp[:signIndex];
        expr = stmp[signIndex+1:];

    return [coef, expr];

#合并同类项,传入的阵列具有['s1', 's2', ..., 'sn']这样的格式
def strcombine(array):
    size = len(array);
    explode = [];
    for i in range(size):
        #这里传入的阵列已经是规格化后的了,否则要加一层strmono处理。
        explode.append(explodemono(monocombine(array[i])));

    result = [];

    for i in range(size):
        size_1 = len(result);

        if size_1 <= 0:
            result.append(explode[i]);
        else:
            for j in range(size_1):
                if result[j][1] == explode[i][1]:
                    result[j][0] = result[j][0] + '+' + explode[i][0];
                    break;

                if j >= size_1-1:
                    result.append(explode[i]);

    result_1 = [];

    size_1 = len(result);
    for j in range(size_1):
        result[j][0] = str(round(eval(result[j][0]), 6));

        if (result[j][0] == '0'):
            result_1.append('(0)');
        else:
            tmps = result[j][1];
            if (tmps == ''):
                result_1.append('('+result[j][0]+')');
            else:            
                result_1.append('('+result[j][0]+')*'+result[j][1]);

    return result_1;

#指数为正整数的乘方
def strpow_n(array, n):
    #计算
    result = [];

    if (n == 1):
        result = array;
    elif (n == 2):
        result = strdot(array, array);

    elif (n >= 3):
        tmp = strdot(array, array);
        n -= 2;

        while (n > 0):            
            result = strdot(tmp, array);
            tmp = result;
            n -= 1;

    return result;

#阵列取负
def minus(array):
    for i in range(len(array)):
        if array[i][1] == '-':
            #array[i][0]是'(, 这是规范
            array[i] = array[i][0]+array[i][2:];
        else:
            array[i] = array[i][0]+'-'+array[i][1:];

    return array;


###
# @usage   代数式运算
# @author  mw
# @date    2016年05月18日  星期三  07:37:01 
# @param
# @return
#
###

#两个多项式相加,合并同类项不在此进行
def stradd(array1, array2):
    #两个多项式相加,这里直接返回数组的相加
    return array1+array2;

#为了简便输入,不要求输入规范化代数式,(coef)*expr形式
#所以在此对多项式进行规范化
#至于单项式规范化,调用strmono函数即可
def strformat(array):
    for i in range(len(array)):
        array[i] = strmono(array[i]);

    return array;
    

#把单项式完全格式化,使经过运算的没运算过的都具有统一的格式
def monoformat(mono):
    #规范化单项式,保证任意两个参数之间都添加一个'*'号
    #这是为了和经过代数式乘法运算之后的格式统一
    chars = len(mono);
    s = '';
    for i in range(chars-1):
        if (mono[i] == ']' or mono[i] == ')') and mono[i+1].isalpha():
            s += mono[i]+'*';
        elif mono[i].isalpha() and mono[i+1].isalpha():
            s += mono[i]+'*';
        #这里还有一个死角,就是下标或指数如果是用的代数式,并且是多项相乘
        #可能会有一点问题,暂时不考虑了
        else:
            s += mono[i];
    s += mono[-1];
    return s;

#把单项式炸开,这里的单项式已经达到最大规范化,是(coef)*x_[1]^[2]*y_[2]^[2]这种结构形式了
#'*'号是要作为分隔符的,不可缺少
def explodemono_2(mono):
    part = mono.split('*');
    #每个部分的[前部,指数部]的对组
    map_ = [];

    for i in range(len(part)):
        expIndex = part[i].find('^');
        if (expIndex != -1):
            map_.append([part[i][:expIndex], part[i][expIndex:]]);
        else:
            s = part[i];
            #系数
            if s[0] == '(':
                map_.append([part[i], '']);
            #代数式
            else:
                map_.append([part[i], '^[1]']);
    map_ = sorted(map_, key = lambda a : a[0]);
    return map_;
        
#单项式同类项合并
def monocombine(mono):
    map_ = explodemono_2(mono);

    size = len(map_);

    result = [];

    for i in range(size):
        size_1 = len(result);

        if (size_1 <= 0):
            result.append(map_[i]);
        else:
            for j in range(size_1):
                if result[j][0] == map_[i][0]:
                    #双方的中括号位置
                    #由于规范化后的原因,这个括号是一定有的
                    p1 = result[j][1].find('[');
                    p2 = result[j][1].find(']');

                    p3 = map_[i][1].find('[');
                    p4 = map_[i][1].find(']');

                    s = result[j][1][p1+1:p2]+'+'+map_[i][1][p3+1:p4];
                    size_2 = len(s);
                    for k in range(size_2):
                        if s[k].isalpha():
                            break;
                        #如果没有字符参数,可以计算出结果,就计算
                        if (k >= size_2-1):
                            s = str(eval(s));
                    result[j][1] = '^['+s+']';
                    break;

                if (j >= size_1-1):
                    result.append(map_[i]);

    size_1 = len(result);

    s = '';

    for i in range(size_1):

        if (i > 0 and result[i][1] == '^[0]'):
            continue;

        s += result[i][0]+result[i][1];

        if (i < size_1-1):
            s += '*';

    return s;



#排列公式  
def arrangement(n, m):  
    if n < m:  
        return arrangement(m, n);  
    else:  
        factorial = 1;  
        for i in range(n, n-m, -1):  
            factorial*=i;  
        return factorial;  
  
#组合公式  
def combination(n, m):  
    if (n < m):  
        return combination(m, n);  
    else:  
        return arrangement(n, m)/arrangement(m,m);


#解一元二次方程
class Equation():
    def quadratic(self, array):
        a, b, c = array[0], array[1], array[2];

        if (a < 0):
            a, b, c = -a, -b, -c;

        p = q = delta = 0;
        x1 = x2 = 0;
        s = '';

        if (a == 0):
            return [-c/b];
        else:
            delta = b**2 - 4*a*c;
            if (delta < 0):
                real = -b/(2*a);
                image = (-delta)**0.5;
                return [complex(real, -image), complex(real, image)];
                        
            else:
                if (abs(delta) < 1e-6):
                    x1 = x2 = -b/(2*a);
                else:
                    x1 = (-b-delta**0.5)/(a*2);
                    x2 = (-b+delta**0.5)/(a*2);

            return [x1, x2];


###
# @usage   数据的集中分析类
# @author  mw
# @date    2016年05月20日  星期五  10:06:47 
# @param
# @return
#
###

class DataAnalyze():
    #由于numpy的方法接口只对narray开放,所以,数组先要格式化一下
    #对于自己的数组而言,这个方法是必须要先调用一下,才能使用numpy方法的
    def format(self, array):
        return numpy.array(array);
    
    #求和
    def sum(self, array):        
        return array.sum();

    #均值
    def average(self, array):
        return self.sum(array)/len(array);
        
    #方差
    def variance(self, array):
        array_ = array*array;
        sum_ = array_.sum();
        aver_ = self.average(array);

        result = sum_/len(array) - aver_**2;
        return result;
    
    #标准差
    def RMS(self, array):
        return (self.variance)**0.5;
        
###
# @usage   多项式运算相关
# @author  mw
# @date    2016年05月23日  星期一  09:36:12 
# @param
# @return
#
###
class Polynomial():
    #格式化打印
    def printPoly(self, array, variable = 'x'):
        len_ = len(array);
        poly = [];
        
        for i in range(len_):
            if (i < len_ -1):
                s = '('+str(array[i])+')*'+variable+'^['+str(len_-1-i)+']';
            else:
                s = '('+str(array[i])+')';
            poly.append(s);

        s = '';
        for i in range(len_):
            s += poly[i];
            if (i < len_ - 1):
                s += '+';
        
        print(s); #格式:(1)*x^[3]+(2)*x^[2]+(-3)*x^[1]+(4)
        return poly;
            
    #解不等式
    def inequality(self, array, symbol = '<'):
        #方程的根
        roots = np.roots(array);
        roots = sorted(roots);
        #print(roots);
        len_ = len(roots);

        p = np.poly1d(array);
        #符合要求的区间
        section = [];

        if (symbol == '<'):
            if (p(roots[0]-1) < 0):
                section.append(['-inf', roots[0]]);
            if (p(roots[len_-1]+1))< 0:
                section.append([roots[len_-1], 'inf']);
        elif (symbol == '>'):
            if (p(roots[0]-1)) > 0:
                section.append(['-inf', roots[0]]);
            if (p(roots[len_-1]+1)) > 0:
                section.append([roots[len_-1], 'inf']);
            
        for i in range(len_-1):
            mid = (roots[i]+roots[i+1])/2;
            if (symbol == '<'):
                if p(mid) < 0:
                    section.append([roots[i], roots[i+1]]);
            elif (symbol == '>'):
                if p(mid) > 0:
                    section.append([roots[i], roots[i+1]]);  
        return section;

    #计算代数式的值
    #代数式具有[(coef)*expr^[exp], ...]这种形式
    #要加载自制的alg模块
    def algValue(self, stralg, valueTable):
        #多项式的项数
        len_s = len(stralg);
        #参数对照表的项数
        #参数对照表具有[['x', '1'], ['y', '3']]这样的形式
        len_v = len(valueTable);

        for i in range(len_s):
            s = stralg[i];

            for j in range(len_v):
                s = s.replace(valueTable[j][0], str(valueTable[j][1]));

            s = s.replace('^[', '**(');
            s = s.replace(']', ')');

            stralg[i] = eval(s);

        return stralg;
            
</span>


<span style="font-size:18px;">import numpy.f2py  
import numpy.random  
import numpy.polynomial  
import numpy.ma  
import numpy.distutils  
import numpy.compat  
import numpy as np;
import numpy.linalg  
import numpy.matrixlib  
import numpy.fft  
import numpy.distutils.fcompiler  
import numpy.core  
import numpy.distutils.command



###
# @usage   对于含有代数符号的等式及相关类型进行计算
# @author  mw
# @date    2016年05月24日  星期二  08:21:57 
# @param
# @return
#
###

#所有输入的字符串都是要符合(coef)*expr这种规范的
#相应转换可以调用alg.strmono处理单项式
#或调用alg.strformat来处理多项式
class StringAlgSolve():
    #格式化输入的多项式阵列
    def format(self, array):
        return alg.strformat(array);

    #把一个字符串阵列表示的多项式,转换成指定变量的系数多项式
    #比如 ['(1/4)x^[2]', '-(1/12)y^[2]', '-1'], 以y作为参数 => ['(-(1/12))', 0, '(1/4)x^[2]+(-1)']
    #传入的格式必须是已经格式化过的(coef)*x^[2]*y_[2]^[3]...这种类似形式
    def coefTransfer(self, array, element):
        coefMap = [];

        len_ = len(array);
        len_2 = len(element);
        
        for i in range(len_):
            s = array[i];
            len_3 = len(s);
            index = s.find(element);

            #参数的0次方
            if (index == -1):
                coefMap.append([array[i], 0]);                
            elif (index+len_2 < len_3 and s[index+len_2] != '^'):
                #参数的一次方
                coefMap.append([s[:index-1]+s[index+len_2:], 1]);
            
            elif (index+len_2 >= len_3):
                #这里回退一个位置是因为根据格式参数之间有一个'*'号相连,要退掉
                coefMap.append([s[:index-1], 1]);
            else:
                #左右中括号作为定界符,这就是为什么要求先格式化
                LBracket = index+len_2+1;
                RBracket = s.find(']', LBracket);
                #幂的次数
                exp_ = int(s[LBracket+1:RBracket]);
                coefMap.append([s[:index-1]+s[index+len_2:], exp_]);
                
        #对coefMap中的项按参数的次数进行合并
        coefMap_2 = [];
        coefMap_2.append(coefMap[0]);
        for i in range(1, len(coefMap)):
            len_3 = len(coefMap_2);
            for j in range(len_3):
                if (coefMap_2[j][1] == coefMap[i][1]):
                    coefMap_2[j][0] = coefMap_2[j][0]+ '+'+coefMap[i][0];
                    break;
                    

                if (j >= len_3-1):
                    coefMap_2.append(coefMap[i]);

        coefMap = coefMap_2; 
                    
        #把系数映射由高到低排列
        coefMap = sorted(coefMap, key = lambda a : a[1], reverse = True);

        #返回的是参数的系数映射表[[coef, exp]...]对组
        return coefMap;

    
    #返回参数的系数阵列
    def coefArray(self, array, element):
        coefMap = self.coefTransfer(array, element);

        len_4 = len(coefMap);
        maxCoef, minCoef = coefMap[0][1], coefMap[len_4-1][1];

        coefArray = ['0']*(maxCoef-minCoef+1);

        for i in range(len_4):
            coefArray[maxCoef-coefMap[i][1]] = coefMap[i][0];

        return coefArray;


    #获取多项式的系数值,比如5x^2+4x+1 = 0应该返回[5, 4, 1]
    def coefPoly(self, array, element):
        coefMap = self.coefTransfer(array, element);

        len_4 = len(coefMap);
        maxCoef, minCoef = coefMap[0][1], coefMap[len_4-1][1];

        coefArray = ['0']*(maxCoef-minCoef+1);

        for i in range(len_4):
            index = coefMap[i][0].find('^');
            if (index != -1):
                s = coefMap[i][0][:index];
            else:
                s = coefMap[i][0];
            #这里是必须要能求值的,这个方法是为了便于调用numpy.roots求多项式的根
            coefArray[maxCoef-coefMap[i][1]] = eval(s);

        return coefArray;

    #求解多项式的根(在参数情况下)
    def solvePoly(self, coefArray):
        len_ = len(coefArray);

        #

        #求解二次方程
        if (len_ == 3):
            a, b, c = str(coefArray[0]), str(coefArray[1]), str(coefArray[2]);
            #注意,由于此处得出的系数阵列是这样的形式:['(-(1/12))', 0, '(1/4)x^[2]+(-1)']
            #已经无法用alg中函数去做任何计算,只能纯粹进行字符串的叠加处理
            
            delta = self.strAdd(self.strPow(b, '2'), self.strMul('-4', self.strMul(a, c)));
            #分子,分母
            numerator = self.strAdd(self.strMinus('0', b), self.strPow(delta, '0.5'));
            numerator2 = self.strMinus(self.strMinus('0', b), self.strPow(delta, '0.5'));
            denomerator = self.strMul('2', a);

            return [self.strDiv(numerator, denomerator),
                    self.strDiv(numerator2, denomerator)];

        #求解一次方程
        if (len_ == 2):
            a, b = str(coefArray[0]), str(coefArray[1]);
            return [self.strDiv(b, self.strMinus('0', a))];

        return '';

    #代数式里的两个代数式相乘,这里就是两个字符串相加的处理而已
    def strMul(self, str1, str2):
        if (self.judgeZero(str1)):
            return '';
        else:
            if (self.judgeZero(str2)):
                return '';
            else:
                return '('+str1+')*('+str2+')';

    #两个代数式相除
    def strDiv(self, str1, str2):
        if (self.judgeZero(str1)):
            return '';
        else:
            if (self.judgeZero(str2)):
                return '(inf)';
            else:
                return '('+str1+')/('+str2+')';

    #代数式相减
    def strMinus(self, str1, str2):
        if (self.judgeZero(str1)):
            if (self.judgeZero(str2)):
                return '';
            else:
                return '(-('+str2+'))';
        else:
            if (self.judgeZero(str2)):
                return '('+str1+')';
            else:
                return '('+str1+')-('+str2+')';

    #代数式相加
    def strAdd(self, str1, str2):
        if (self.judgeZero(str1)):
            if (self.judgeZero(str2)):
                return '';
            else:
                return '('+str2+')';
        else:
            if (self.judgeZero(str2)):
                return '('+str1+')';
            else:
                return '('+str1+')+('+str2+')';
    

    #代数式里的代数式乘方,这里就是字符串的处理而已
    def strPow(self, str1, str2):
        str2 = str(str2);
        if (self.judgeZero(str1)):
            return '';
        else:
            if (self.judgeZero(str2)):
                return '('+str1+')';
            else:
                return '('+str1+')^['+str2+']';

    #判断字符串是否为0  
    def judgeZero(self, str1):
        for i in range(len(str1)):
            if (str1[i].isdigit() and str1[i] != '0'):
                #存在数字不为0, 所以这个代数式不为0
                return False;
            #由于在规范化输出时已经保证了如果系数为0, 无论有多少参数都取0
            #所以只要存在参数就说明代数式不为0
            elif (str1[i].isalpha()):
                return False;

        return True;

    #给参数赋值,计算代数式的值
    #比如输入 ('x^[2]+1', 'x', 3) => 10
    #要确保给的条件足以让代数式计算出数值,否则肯定报错
    def strEval(self, str1, element, elementValue):
        #代入数值,去指数
        str1 = str1.replace(element, str(elementValue));
        str1 = str1.replace('^[', '**');
        str1 = str1.replace(']', '');

        return eval(str1);

    #对于本身不带参数的字符串,清除格式即可计算出数值
    def arrayEval(self, array):
        for i in range(len(array)):
            str1 = array[i];
            str1 = str1.replace('^[', '**');
            str1 = str1.replace(']', '');
            str1 = eval(str1);
            array[i] = str1;

        return array;</span>

本节到此结束,欲知后事如何,请看下回分解。

你可能感兴趣的:([从头学数学] 第221节 带着计算机去高考(十三))