[从头学数学] 第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节 带着计算机去高考的主要内容,如果未能解决你的问题,请参考以下文章