本文主要是介绍[从头学数学] 第219节 带着计算机去高考(十一),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
[机器小伟]在[工程师阿伟]的陪同下进入了[九转金丹]之第八转的修炼。设想一个场景:
如果允许你带一台不连网的计算机去参加高考,你会放弃选择一个手拿计算器和草稿本吗
?阿伟决定和小伟来尝试一下用计算机算高考题会是怎样的感觉。
正剧开始:
星历2016年05月24日 12:49:39, 银河系厄尔斯星球中华帝国江南行省。
[工程师阿伟]正在和[机器小伟]一起做着2010年的江苏省数学高考题]。
2010年江苏的这张高考试卷,是大家公认的一张难卷,难出了风格,
难出了特色,也难出了名。
想来世事也是如此无常,这一年的考生想必心里会想,这三届师兄们
做的题那就像玩一样,为啥轮到自己时会撞铁板呢。真是时也命也。好在
由于题量大,鸡蛋没放在一个篮子里,所以有切肤之痛的人应该不太多。
这一年的考卷,阿伟给评为6环,因为所有的题基本都是四、五环的难度,
然后题量还这么大。
<span style="font-size:18px;"> //题1if (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;"> //题5if (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, 所以这个代数式不为0return False;#由于在规范化输出时已经保证了如果系数为0, 无论有多少参数都取0#所以只要存在参数就说明代数式不为0elif (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;"> //题6if (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;"> //题8if (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节 带着计算机去高考(十一)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!