为啥说函数是一等公民
论道无法目前无法用markdown语法
http://note.youdao.com/noteshare?id=7a2cfa7d7397bbd77cb6a511dcb61ce6
如果不懂递归,请先看上面的链接,并建议了解递归后再观看这篇文章
http://note.youdao.com/noteshare?id=617c42737cbb47e6ea258ccdda3b869a
可以直接访问链接# 函数是一等公民
## 初步抽象
看下面的三个过程
给出两个参数 a 和 b,计算出:a到b之间的各个整数之和(包含a和b),例如: 1+2+3+4..
给出两个参数 a 和 b,计算出:a到b之间的各个整数的立方之和(包含a和b),例如: 1的立方+2的立方+3的立方
给出两个参数 a 和 b,计算出:a到b之间的各个奇数(包含a和b),与相邻的数字两两相乘为分母,1为分子的分数的和,例如: 1/(1 * 3) + 1/(5 * 7) + 1/(9 * 11)
试寻找三者的相同点,抽象出一个函数sum,这个函数接受四个参数,a,b和两个函数,使得三个过程可以共享相同的逻辑框架(第三个稍微难一点,但还是可以复用的)
### 观察
1+2+3+4..
1的立方+2的立方+3的立方
1/(1 * 3) + 1/(5 * 7) + 1/(9 * 11)
### 提出相似结构
1+##(2+3+4..)##
1的立方+##(2的立方+3的立方 )##
1/(1 * 3) + ##(1/(5 * 7) + 1/(9 * 11))##
```
function sum(term , start , next , end){
if(start > end){return 0}
//如果当前值(start一开始是开始值,但是对于每一步是当前参数)大于最后的一个数,说明累加到最后了,输出一个零代表结束
//累积相当于两个部分, 第一个值 与 剩下的值
//term(start) 是根据 当前值 获得对应的值
//其他的不管,用递归的思想把后续扔回给同名函数
return term(start) + sum(term, next(start) , next , end),
}
```
product函数接受四个参数a,b和两个函数。product用于计算给定范围(a到b)的某个函数值的乘积。
比如2~6之间每个数的3倍积
(2 * 3) * (3 * 3) * (4 * 3) * (5 * 3) * (6 * 3)
### 观察
(2 * 3) * (3 * 3) * (4 * 3) * (5 * 3) * (6 * 3)
### 提取相似结构
(2 * 3) * ###(3 * 3) * (4 * 3) * (5 * 3) * (6 * 3)###
```
function product(term, start , next , end){
if(start > end){return 1}
//乘法的结束 为 *1
// 累积 前后关系 是通过 乘号来结合起来 (combiner) 的
return term(start) * product(term , next(start) , next ,end)
}
```
## 再次抽象
sum和product都是另一种成为accumulate的特殊情况而已。现在想方法用accumulate覆盖 sum 和 product 算法
### 观察
```
function sum(term , start , next , end){
if(start > end){return 0}
return term(start) + sum(term, next(start) , next , end)
}
function product(term, start , next , end){
if(start > end){return 1}
return term(start) * product(term , next(start) , next ,end)
}
```
### 提出相似结构 区分 不同点
```
if(start > end){return 0}
if(start > end){return 1}
//不同点为 结束返回值 作为 一种参数 output
term(start) + sum(term, next(start) , next , end)
term(start) * product(term , next(start) , next ,end)
//中间的 结合方式不同 把结合方式 当作一种参数 sum 与 product 也是 accumulate的形式的一种 不断套用
```
现在accumulate使用的是与sum和product一样的参数项和范围描述参数,再加上一个(两个参数的)combiner函数和一个 output 参数。
```
function accumulate(combiner , output ,term, start , next , end ){
if(start > end){return output}
return combiner( term(start) , accumulate(combiner , output , term , next(start) , next ,end))
}
```
写一个filtered-accumulate,表现更加通用的能力。过滤掉一些 值
例如
我们通过filter挑出1到100的偶数,然后计算sum或product。
```
function filter (x){
if (x%2 == 0) {
return true;
}
return false;
}
```
### 分析 filter 作用在 start 上面 根据start 来判断是否进行 结合两个值 还是 放到再一次符合要求的 start 值 才结合两个值
```
function filtered_accumulate(filter, combiner, output, term, start, next, end) {
if(start > end){return output}
if(filter(start)){
return combiner(term(start),filtered_accumulate(filter, combiner , output , term , next(start) , next , end))
}else{
return filtered_accumulate(filter,combiner,output,term,next(start),next,end)
}
}
```
## 附加题 严重超纲
计算正切函数
tan x = x/(1 - x * x/(3 - x * x/(5 - x * x/(7 - x * x.....))))
其中x表示弧度,我们用tag_cf(x, k)定义这个过程
其中x表示弧度,k表示计算的项数。
这里面用到的就是所谓的连分式。
## 从零开始抽象
牛顿法逼近函数fun(x) = 0的一个数值解,其中x的定义域实数全部。
```
function fun(x){
return x+x*x - 10
//一元二次方程
}
```
```
solve(fun, x, dx)
```
solve返回result,result是正确解的近似值 其中fun为f(x)这个函数, x是输入的一个用来逼近起始点(任何实数都可以),我们可以理解他是我们认为接近正确解的值类似上面的start,
dx是fun(不是x的x(不断靠近))-0的误差值
这个误差值小于dx我们认为x是符合我们逼近要求的近似解。
类似上面的终止条件 start > end
现在变成一个根据 x 与 dx 的函数
逼近的具体方法,伪代码如下:
根据牛顿微分方程
dy = (fun(x+dx)-fun(x))
导数 = dy/dx
```
diff(x) = (fun(x+dx)-fun(x))/dx;
```
误差值就是 存在导数(如果导数为零就是我们的目标结果)带来的
我们现在要缩减误差 , 逼近后的一个值,
根据高中知识通过导数 与当前点做 三角形
函数在x点的斜率,函数x点上做切线,QQ这条切线与x轴的焦点一定在要求的值的一边并像最终结果靠近。
```
next(x) = x - fun(x)/diff(x)
```
```
function solve(fun, x, dx){
if( dx > Math.abs(fun(x))){return x}
//先对 fun(x)去绝对值,看看是否符合我们要求的误差
function next(x) {
return x - fun(x)/diff(x)
}
//如果不符合,我们要想方法求出 向它逼急的方法
function diff(x){
return (fun(x+dx)-fun(x))/dx;
}
//逼近的点依赖与导数计算
//把逼近点递归到同名方程/函数,不断逼近
return solve(fun,next(x),dx)
}
```
## 再度抽象
写一个复合函数f(g(x))的实现,compose(f,g),其中f和g是两个函数的运算过程 他返回一个函数过程,
### 思考
如果 值返回 f(x) 是怎么的
```
function compose(f,g){
return function(x){
return f(x)
}
}
```
然后进一步 返回 f(g(x))
```
function compose (f, g){
return function(x){
return f(g(x))
}
}
```
刚才只是热身
现在通过微分进行迭代查找方程解的,这道题我们通过传入检验过程和逼近过程,得到返回的函数过程来解决解方程的问题。
solve_iter(check, buzz)
读懂不了吧
其实就是复合函数的一种
先要进行检查函数
然后进行逼近函数
```
function solve_iter(check, buzz)
{
return function(fun,x,dx)
{
if (check(fun,x,dx)){return x}
// 检查一下是否我们要求
//否则 逼近下一步
else{
var x = buzz(fun,x,dx)
//下一个x 给好的函数 与参数求出来
// 由于这里是要递归逼近, 就把,其他所有不变的参数,一起当作参数送出去
//如何送出去呢,先调用一次 solver_iter 就行
return solve_iter(check,buzz)(fun,x,dx)
}
}
}
```
# 把每一步的实现方式都抽象后,整体的逻辑不变,但是每一个子方程都变得异常简单
http://note.youdao.com/noteshare?id=7a2cfa7d7397bbd77cb6a511dcb61ce6
如果不懂递归,请先看上面的链接,并建议了解递归后再观看这篇文章
http://note.youdao.com/noteshare?id=617c42737cbb47e6ea258ccdda3b869a
可以直接访问链接# 函数是一等公民
## 初步抽象
看下面的三个过程
给出两个参数 a 和 b,计算出:a到b之间的各个整数之和(包含a和b),例如: 1+2+3+4..
给出两个参数 a 和 b,计算出:a到b之间的各个整数的立方之和(包含a和b),例如: 1的立方+2的立方+3的立方
给出两个参数 a 和 b,计算出:a到b之间的各个奇数(包含a和b),与相邻的数字两两相乘为分母,1为分子的分数的和,例如: 1/(1 * 3) + 1/(5 * 7) + 1/(9 * 11)
试寻找三者的相同点,抽象出一个函数sum,这个函数接受四个参数,a,b和两个函数,使得三个过程可以共享相同的逻辑框架(第三个稍微难一点,但还是可以复用的)
### 观察
1+2+3+4..
1的立方+2的立方+3的立方
1/(1 * 3) + 1/(5 * 7) + 1/(9 * 11)
### 提出相似结构
1+##(2+3+4..)##
1的立方+##(2的立方+3的立方 )##
1/(1 * 3) + ##(1/(5 * 7) + 1/(9 * 11))##
```
function sum(term , start , next , end){
if(start > end){return 0}
//如果当前值(start一开始是开始值,但是对于每一步是当前参数)大于最后的一个数,说明累加到最后了,输出一个零代表结束
//累积相当于两个部分, 第一个值 与 剩下的值
//term(start) 是根据 当前值 获得对应的值
//其他的不管,用递归的思想把后续扔回给同名函数
return term(start) + sum(term, next(start) , next , end),
}
```
product函数接受四个参数a,b和两个函数。product用于计算给定范围(a到b)的某个函数值的乘积。
比如2~6之间每个数的3倍积
(2 * 3) * (3 * 3) * (4 * 3) * (5 * 3) * (6 * 3)
### 观察
(2 * 3) * (3 * 3) * (4 * 3) * (5 * 3) * (6 * 3)
### 提取相似结构
(2 * 3) * ###(3 * 3) * (4 * 3) * (5 * 3) * (6 * 3)###
```
function product(term, start , next , end){
if(start > end){return 1}
//乘法的结束 为 *1
// 累积 前后关系 是通过 乘号来结合起来 (combiner) 的
return term(start) * product(term , next(start) , next ,end)
}
```
## 再次抽象
sum和product都是另一种成为accumulate的特殊情况而已。现在想方法用accumulate覆盖 sum 和 product 算法
### 观察
```
function sum(term , start , next , end){
if(start > end){return 0}
return term(start) + sum(term, next(start) , next , end)
}
function product(term, start , next , end){
if(start > end){return 1}
return term(start) * product(term , next(start) , next ,end)
}
```
### 提出相似结构 区分 不同点
```
if(start > end){return 0}
if(start > end){return 1}
//不同点为 结束返回值 作为 一种参数 output
term(start) + sum(term, next(start) , next , end)
term(start) * product(term , next(start) , next ,end)
//中间的 结合方式不同 把结合方式 当作一种参数 sum 与 product 也是 accumulate的形式的一种 不断套用
```
现在accumulate使用的是与sum和product一样的参数项和范围描述参数,再加上一个(两个参数的)combiner函数和一个 output 参数。
```
function accumulate(combiner , output ,term, start , next , end ){
if(start > end){return output}
return combiner( term(start) , accumulate(combiner , output , term , next(start) , next ,end))
}
```
写一个filtered-accumulate,表现更加通用的能力。过滤掉一些 值
例如
我们通过filter挑出1到100的偶数,然后计算sum或product。
```
function filter (x){
if (x%2 == 0) {
return true;
}
return false;
}
```
### 分析 filter 作用在 start 上面 根据start 来判断是否进行 结合两个值 还是 放到再一次符合要求的 start 值 才结合两个值
```
function filtered_accumulate(filter, combiner, output, term, start, next, end) {
if(start > end){return output}
if(filter(start)){
return combiner(term(start),filtered_accumulate(filter, combiner , output , term , next(start) , next , end))
}else{
return filtered_accumulate(filter,combiner,output,term,next(start),next,end)
}
}
```
## 附加题 严重超纲
计算正切函数
tan x = x/(1 - x * x/(3 - x * x/(5 - x * x/(7 - x * x.....))))
其中x表示弧度,我们用tag_cf(x, k)定义这个过程
其中x表示弧度,k表示计算的项数。
这里面用到的就是所谓的连分式。
## 从零开始抽象
牛顿法逼近函数fun(x) = 0的一个数值解,其中x的定义域实数全部。
```
function fun(x){
return x+x*x - 10
//一元二次方程
}
```
```
solve(fun, x, dx)
```
solve返回result,result是正确解的近似值 其中fun为f(x)这个函数, x是输入的一个用来逼近起始点(任何实数都可以),我们可以理解他是我们认为接近正确解的值类似上面的start,
dx是fun(不是x的x(不断靠近))-0的误差值
这个误差值小于dx我们认为x是符合我们逼近要求的近似解。
类似上面的终止条件 start > end
现在变成一个根据 x 与 dx 的函数
逼近的具体方法,伪代码如下:
根据牛顿微分方程
dy = (fun(x+dx)-fun(x))
导数 = dy/dx
```
diff(x) = (fun(x+dx)-fun(x))/dx;
```
误差值就是 存在导数(如果导数为零就是我们的目标结果)带来的
我们现在要缩减误差 , 逼近后的一个值,
根据高中知识通过导数 与当前点做 三角形
函数在x点的斜率,函数x点上做切线,QQ这条切线与x轴的焦点一定在要求的值的一边并像最终结果靠近。
```
next(x) = x - fun(x)/diff(x)
```
```
function solve(fun, x, dx){
if( dx > Math.abs(fun(x))){return x}
//先对 fun(x)去绝对值,看看是否符合我们要求的误差
function next(x) {
return x - fun(x)/diff(x)
}
//如果不符合,我们要想方法求出 向它逼急的方法
function diff(x){
return (fun(x+dx)-fun(x))/dx;
}
//逼近的点依赖与导数计算
//把逼近点递归到同名方程/函数,不断逼近
return solve(fun,next(x),dx)
}
```
## 再度抽象
写一个复合函数f(g(x))的实现,compose(f,g),其中f和g是两个函数的运算过程 他返回一个函数过程,
### 思考
如果 值返回 f(x) 是怎么的
```
function compose(f,g){
return function(x){
return f(x)
}
}
```
然后进一步 返回 f(g(x))
```
function compose (f, g){
return function(x){
return f(g(x))
}
}
```
刚才只是热身
现在通过微分进行迭代查找方程解的,这道题我们通过传入检验过程和逼近过程,得到返回的函数过程来解决解方程的问题。
solve_iter(check, buzz)
读懂不了吧
其实就是复合函数的一种
先要进行检查函数
然后进行逼近函数
```
function solve_iter(check, buzz)
{
return function(fun,x,dx)
{
if (check(fun,x,dx)){return x}
// 检查一下是否我们要求
//否则 逼近下一步
else{
var x = buzz(fun,x,dx)
//下一个x 给好的函数 与参数求出来
// 由于这里是要递归逼近, 就把,其他所有不变的参数,一起当作参数送出去
//如何送出去呢,先调用一次 solver_iter 就行
return solve_iter(check,buzz)(fun,x,dx)
}
}
}
```
# 把每一步的实现方式都抽象后,整体的逻辑不变,但是每一个子方程都变得异常简单
0 个回答