[从头学数学] 第219节 带着计算机去高考

Posted mwsister

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[从头学数学] 第219节 带着计算机去高考相关的知识,希望对你有一定的参考价值。

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

正剧开始:

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


2010年江苏的这张高考试卷,是大家公认的一张难卷,难出了风格,

难出了特色,也难出了名。


想来世事也是如此无常,这一年的考生想必心里会想,这三届师兄们

做的题那就像玩一样,为啥轮到自己时会撞铁板呢。真是时也命也。好在

由于题量大,鸡蛋没放在一个篮子里,所以有切肤之痛的人应该不太多。


这一年的考卷,阿伟给评为6环,因为所有的题基本都是四、五环的难度,

然后题量还这么大。








<span style="font-size:18px;">	//题1
	if (1) {
		var mathText = new MathText();
		
		//希腊字母表(存此用于Ctrl C/V
			//ΑΒΓΔΕΖΗ ΘΙΚΛΜΝΞ ΟΠΡ ΣΤΥ ΦΧΨ Ω
			//αβγδεζη θικλμνξ οπρ στυ φχψ ω
			
		//希腊大小写字母
		var Gc = 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ';
		var Gs = 'αβγδεζηθικλμνξοπρστυφχψω';
		
		
		
		var s = [
			'a + 2 = 3  => a = 1',
			'a^[2] + 4 = 3 => a = NULL',
			'=> a = 1'
			
			
		];
		
		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>



<span style="font-size:18px;">#题2
def tmp2():
    z = (6+4j)/(2-3j);
    print(abs(z));
	
>>> 
2.0</span>


<span style="font-size:18px;">#题3
def tmp3():
    P = 1-alg.combination(3, 2)/alg.combination(4, 2);
    print(P);

>>> 
0.5</span>


<span style="font-size:18px;">#题4
def tmp4():
    p = [0.01, 0.01, 0.04,0.06, 0.05, 0.02, 0.01];
    n = sum(p[:3])/sum(p)*100;
    print(n);
        
>>> 
30.0</span>



<span style="font-size:18px;">	//题5
	if (1) {
		var mathText = new MathText();
		
		//希腊字母表(存此用于Ctrl C/V
			//ΑΒΓΔΕΖΗ ΘΙΚΛΜΝΞ ΟΠΡ ΣΤΥ ΦΧΨ Ω
			//αβγδεζη θικλμνξ οπρ στυ φχψ ω
			
		//希腊大小写字母
		var Gc = 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ';
		var Gs = 'αβγδεζηθικλμνξοπρστυφχψω';
		
		
		
		var s = [
			'f(1) = (e+ae^[-1])',
			'f(-1) = -(e^[-1]+ae)',
			'f(1) == f(-1) => a = -1'
			
			
		];
		
		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>




为了做这个题,阿伟也是拼了,不是说这个题多难,而是阿伟要借这个题来做一个大工具。

然后工具出炉了:

<span style="font-size:18px;">###
# @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[coefMap[i][1]] = coefMap[i][0];

        coefArray.reverse();

        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):
        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);
        
    
</span>


这个工具能做的事很强大:

<span style="font-size:18px;">#题6
def tmp6():
    #
    solve = StringAlgSolve();
    f = ['(1/4)x^[2]', '-(1/12)y^[2]', '-1'];
    f = solve.format(f);
    print(f); #['(1/4)x^[2]', '(-(1/12))*y^[2]', '(-1)']

    coef_y = solve.coefArray(f, 'y');
    print(coef_y);
    '''
    ['(((((-4)*(((-(1/12)))*((1/4)*x^[2]+(-1)))))^[0.5]))/((2)*((-(1/12))))',
    '((-((((-4)*(((-(1/12)))*((1/4)*x^[2]+(-1)))))^[0.5])))/((2)*((-(1/12))))']
    '''
    roots = solve.solvePoly(coef_y);
    print(roots);

    
    #双曲线右焦点
    F = [4, 0];
    
    for i in range(len(roots)):
        roots[i] = solve.strEval(roots[i], 'x', 3);
        distance = geo.distance2D([3, roots[i]], F);
        print(distance);

    print(roots); #[-3.872983346207417, 3.872983346207417]
	
>>> 
['(1/4)*x^[2]', '(-(1/12))*y^[2]', '(-1)']
['(-(1/12))', '0', '(1/4)*x^[2]+(-1)']
['(((((-4)*(((-(1/12)))*((1/4)*x^[2]+(-1)))))^[0.5]))/((2)*((-(1/12))))', '((-((((-4)*(((-(1/12)))*((1/4)*x^[2]+(-1)))))^[0.5])))/((2)*((-(1/12))))']
4.0
4.0
[-3.872983346207417, 3.872983346207417]</span>

不得不说,这是[工程题阿伟]的一小步,却是[机器小伟]的一大步。

因为从此以后,[机器小伟]正式进入了可以解人族题的行列。


从很久以前阿伟一直在期待着Matlab或者python能放出一款能够这样解题

的程式,但人家却总是不出,没办法,自己动手吧。


现在既然阿伟有了,大家也就都有了。



<span style="font-size:18px;">	//题6
	if (1) {
		var mathText = new MathText();
		
		//希腊字母表(存此用于Ctrl C/V
			//ΑΒΓΔΕΖΗ ΘΙΚΛΜΝΞ ΟΠΡ ΣΤΥ ΦΧΨ Ω
			//αβγδεζη θικλμνξ οπρ στυ φχψ ω
			
		//希腊大小写字母
		var Gc = 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ';
		var Gs = 'αβγδεζηθικλμνξοπρστυφχψω';
		
		
		
		var s = [
			'(((((-4)*(((-(1/12)))*((1/4)*x^[2]+(-1)))))^[0.5]))',
			'/((2)*((-(1/12))))',
			'((-((((-4)*(((-(1/12)))*((1/4)*x^[2]+(-1)))))^[0.5])))',
			'/((2)*((-(1/12))))'
			
			
		];
		
		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>




<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 = 2, spaceY = 2;           
        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]/16 = 1', f2 = '', f3 = '', f4 = '';        
            
  
        //函数描点    
        //参数方程  
        var x, y;  
        var pointA = [];  
          
        for (var thita = 0; thita < Math.PI*2; thita +=Math.PI/24) {  
            a.push([2/Math.cos(thita), 2*1.732*Math.tan(thita)]);  
        }  
          
                  
        //存放临时数组        
        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, -180, 200);          
        }  
  
          
    }
	</span>



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

    while (S < 33):
        S = S + 2**n;

        if (S >= 33):
            break;

        n += 1;

    print(S);</span>




这个题就可以用上面那个工具来解,阿伟给大家展示下过程:


<span style="font-size:18px;">#题8
def tmp8():
    solve = StringAlgSolve();
    f = ['a_[k]^[2]', '-2a_[k]^[2]', '2a_[k]a_[k+1]'];
    f = solve.format(f);
    print('step 1: ', f); #['(1)*a_[k]^[2]', '(-2)*a_[k]^[2]', '(2)*a_[k]*a_[k+1]']

    g = solve.coefTransfer(f, 'a_[k+1]');
    print('step 2: ', g); #[['(2)*a_[k]', 1], ['(1)*a_[k]^[2]+(-2)*a_[k]^[2]', 0]]

    g = solve.coefArray(f, 'a_[k+1]');
    print('step 3: ', g); #['(2)*a_[k]', '(1)*a_[k]^[2]+(-2)*a_[k]^[2]']

    h = solve.solvePoly(g);
    print('step 4: ', h);

    a1 = 16;
    
    res = [];
    res.append(a1);

    for i in range(5):
        a_n = solve.strEval(h[0], 'a_[k]', res[-1]);
        res.append(a_n);

    print('step 5: ', res); #[16, 8.0, 4.0, 2.0, 1.0, 0.5]

    answer = res[0] + res[2] + res[4];
    print('step 6: ', answer);
    
>>> 
step 1:  ['(1)*a_[k]^[2]', '(-2)*a_[k]^[2]', '(2)*a_[k]*a_[k+1]']
step 2:  [['(2)*a_[k]', 1], ['(1)*a_[k]^[2]+(-2)*a_[k]^[2]', 0]]
step 3:  ['(2)*a_[k]', '(1)*a_[k]^[2]+(-2)*a_[k]^[2]']
step 4:  ['((1)*a_[k]^[2]+(-2)*a_[k]^[2])/((-((2)*a_[k])))']
step 5:  [16, 8.0, 4.0, 2.0, 1.0, 0.5]
step 6:  21.0</span>

就是这么个过程,然后得到了正确的结果。

虽然工具草创,这条经脉还很弱,但毕竟是真正的打通了,以后添砖加瓦,

大有可为的。






倒数第二行是直接把生成的数据显示出来,这样,连打字都省了。


以后你会怎样做题? [机器小伟]已经可以为你代劳了。


<span style="font-size:18px;">	//题8
	if (1) {
		var mathText = new MathText();
		
		//希腊字母表(存此用于Ctrl C/V
			//ΑΒΓΔΕΖΗ ΘΙΚΛΜΝΞ ΟΠΡ ΣΤΥ ΦΧΨ Ω
			//αβγδεζη θικλμνξ οπρ στυ φχψ ω
			
		//希腊大小写字母
		var Gc = 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ';
		var Gs = 'αβγδεζηθικλμνξοπρστυφχψω';
		
		
		
		var s = [
			'y = x^[2]',
			'y\\' = 2x',
			'a_[k]^[2] = 2a_[k](a_[k]-a_[k+1])',
			'a_[k+1] = ((1)*a_[k]^[2]+(-2)*a_[k]^[2])/((-((2)*a_[k])))',
			'a_[1] = 16',
			
			
			
		];
		
		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>


时间不够了,下面阿伟就直接交白卷了。贴一下题。

























这一年的附加题和上一年是两个极端,这一次非常的难。















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


以上是关于[从头学数学] 第219节 带着计算机去高考的主要内容,如果未能解决你的问题,请参考以下文章

[从头学数学] 第214节 带着计算机去高考

[从头学数学] 第211节 带着计算机去高考

[从头学数学] 第209节 带着计算机去高考

[从头学数学] 第215节 带着计算机去高考

[从头学数学] 第216节 带着计算机去高考

[从头学数学] 第217节 带着计算机去高考