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

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

正剧开始:

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


这一年的题难度和上一年持平,可能在正卷部分稍难点,但附加卷

就是送分啦,二三环的难度,估计20分钟内可以解完四道附加题。


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


还是那句话:单道题难度其实只有四环难度,只是因为要解答的题多,拉升了整张卷子的难度。


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




<span style="font-size:18px;">#题1
def tmp1():
    z_1 = 4+29j;
    z_2 = 6+9j;

    z = (z_1 - z_2)*(1j);

    real = z.real;
    print(real);
	
>>> 
-20.0</span>




<span style="font-size:18px;">#题2
def tmp2():
    A = 30;
    a = 2;
    b = 3**0.5;

    ab = a*b*math.cos(A/180*math.pi);
    print(ab);
	
>>> 
3.0</span>




<span style="font-size:18px;">#题3
def tmp3():
    poly = Polynomial();

    f_x = [1, -15, -33, 6];
    #函数的导数
    f_x_der = np.polyder(f_x);

    #print(f_x_der);
    descend = poly.inequality(f_x_der, '<');
    print(descend);
	
>>> 
[[-1.0, 11.0]]</span>



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


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


2008年以前的排列组合那块的那些难题从此一去不返,变成了这种送分的题。



<span style="font-size:18px;">#题6
def tmp6():
    A = [6, 7, 7, 8, 7]
    B = [6, 7, 6, 7, 9]
    
    analyze = alg.DataAnalyze();

    A = analyze.format(A);
    B = analyze.format(B);
    s2_A = analyze.variance(A);
    s2_B = analyze.variance(B);

    print(s2_A, s2_B);
	
>>> 
0.4 1.2</span>


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


这个题比较阴险,主要是一但S>=0 ,T就不再重求,但口算反而不易错。

<span style="font-size:18px;">#题7
def tmp7():
    S = 0;
    T = 1;

    while (S < 10):
        S = T*T - S;
		if (s > 10):
			break;
        T = T + 2;
        print('S, T = {0}, {1}'.format(S, T));

    W = S + T;
    print(W);
	
>>> 
S, T = 1, 3
S, T = 8, 5
S, T = 17, 5
22</span>



这个就是送分题的典型代表,就这个难度,算一环吧。




<span style="font-size:18px;">#题9
def tmp9():
    #曲线C及其导数
    curve_C = [1, 0, -10, 3];
    curve_C_val = np.poly1d(curve_C);
    curve_C_der = np.polyder(curve_C);
    print(curve_C_der);

    quadratic = np.polyadd(curve_C_der, [-2]);
    print(quadratic);

    root = np.roots(quadratic);
    print(root);
    
    for i in range(len(root)):
        print([root[i], curve_C_val(root[i])]);
		
>>> 
[  3   0 -10]
[  3   0 -12]
[ 2. -2.]
[2.0000000000000004, -8.9999999999999982]
[-1.9999999999999996, 15.0]</span>




<span style="font-size:18px;">#题10
def tmp10():
    a = (5**0.5-1)/2;
    b = [[-1, 1], [2, 3], [-3, -2]];
    
    for i in range(len(b)):
        f_m = a**(b[i][0]);
        f_n = a**(b[i][1]);

        print('{0} -- {1}, {2}'.format(i, f_m, f_n));

>>> 
0 -- 1.6180339887498947, 0.6180339887498949
1 -- 0.3819660112501052, 0.23606797749978975
2 -- 4.236067977499789, 2.6180339887498945</span>






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


<span style="font-size:18px;">#题13
def tmp13():
    #假定
    a, b = 2, 1;
    a2 = a*a;
    b2 = b*b;
    c = (a2-b2)**0.5;

    #点
    A_1 = [-a, 0];
    B_2 = [0, b];
    B_1 = [0, -b];
    F = [c, 0];

    #求T点
    T = geo.crossPointOfTwoLine([A_1, B_2], [B_1, F]);

    print(T); #[25.856406460551007, 13.928203230275503]

    #如果已知a, b倒是可以求出交点Y, 现在全是代数
    #真不好求,先放着吧
</span>


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


<span style="font-size:18px;">#题14
def tmp14():
    b = [-53, -23, 19, 37, 82];
    b = [19, -23, 37, -53, 82];
    for i in range(len(b)):
        b[i] = b[i] - 1;

    print(b); #[18, -24, 36, -54, 81]

    for i in range(len(b) - 1):
        print(b[i+1]/b[i]); # q = -1.5
</span>


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


<span style="font-size:18px;">#题15
def tmp15():
    val = [['A_[c]', 'cosa'], ['A_[s]', 'sina'],
           ['B_[c]', 'cosb'], ['B_[s]', 'sinb']];

    a = alg.strformat(['4A_[c]', 'A_[s]']);
    b = alg.strformat(['B_[s]', '4B_[c]']);
    c = alg.strformat(['B_[c]', '-4B_[s]']);
    d = alg.strformat(['-2']);

    #e = b - 2c
    e = alg.stradd(b, alg.strdot(c, d));
    e = alg.strcombine(e);
    print(e); #['(9)*B_[s]^[1]', '(2)*B_[c]^[1]']

    #求a 与(b-2c)的乘积
    f = alg.strdot(a, e);
    f = alg.strcombine(f);

    print(f);
	#['(36)*A_[c]^[1]*B_[s]^[1]', '(8)*A_[c]^[1]*B_[c]^[1]',
    #'(9)*A_[s]^[1]*B_[s]^[1]', '(2)*A_[s]^[1]*B_[c]^[1]']
	
	#得出了一个关系式,但离解决还有好几环</span>




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


<span style="font-size:18px;">#题17
def tmp17():
    a1 = alg.strformat(['a_[1]']);
    a2 = alg.strformat(['a_[1]', 'd']);
    a3 = alg.strformat(['a_[1]', '2d']);
    a4 = alg.strformat(['a_[1]', '3d']);
    a5 = alg.strformat(['a_[1]', '4d']);
    a6 = alg.strformat(['a_[1]', '5d']);
    a7 = alg.strformat(['a_[1]', '6d']);

    #第一个等式
    f_1 = alg.strcombine(alg.strpow_n(a2, 2)+ alg.strpow_n(a3, 2));
    f_2 = alg.strcombine(alg.strpow_n(a4, 2)+alg.strpow_n(a5, 2));
    f_3 = alg.strcombine(alg.stradd(f_1, alg.minus(f_2)));
    print(f_1); 
    print(f_2);
    print(f_3); #这个式子是:['(0)', '(-8)*a_[1]^[1]*d^[1]', '(-20)*d^[2]']
    #所以a_[1] = -2.5d

    #第二个式子
    sum_ = alg.strcombine(a1+a2+a3+a4+a5+a6+a7);

    print(sum_); #['(7)*a_[1]^[1]', '(21)*d^[1]'] = 7
    #所以2d = 7, d = -5 a_[1] = 2
	
>>> 
['(2)*a_[1]^[2]', '(6)*a_[1]^[1]*d^[1]', '(5)*d^[2]']
['(-2)*a_[1]^[2]', '(-14)*a_[1]^[1]*d^[1]', '(-25)*d^[2]']
['(0)', '(-8)*a_[1]^[1]*d^[1]', '(-20)*d^[2]']
['(7)*a_[1]^[1]', '(21)*d^[1]']</span>

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


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




下面就是送分的附加题了:




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


<span style="font-size:18px;">#题21
def tmp21B():
    A = [[3, 2], [2, 1]];

    B = np.linalg.inv(A);
    print(B);

    C = np.dot(A, B);
    print(C);
    
>>> 
[[-1.  2.]
 [ 2. -3.]]
[[ 1.  0.]
 [ 0.  1.]]
 </span>

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




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


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


这些题每个的分数都好拿,估计考生郁闷的是时间不够。


下面贴一下工具:

<span style="font-size:18px;">#一般要包含这几个模块(都写出来了)
import math;
import geo;
import alg;

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
</span>

代数式的运算,有了这个才能玩:

<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 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] == ']' 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;
        
</span>


这个是多项式的,比较可有可无:

<span style="font-size:18px;">###
# @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>


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


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