0.简介
函数或者说方程,在编程语言中,直接就能通过指定变量和系数进行计算,这里主要是利用编程语言来实现这个计算。
1.方程的表示
一般来说,一个方程如,在计算机中可以表示成
,实际的代码如下
y = x*x
当计算y的时候,给x指定值即可,如
float x = 0, y = 0;
for (int i = 0; i < 10; i++)
{
y = x * x;
cout << y << endl;
}
当方程更加复杂的时候。
float x = 0, y = 0;
for (int i = 0; i < 10; i++)
{
y = x * x + 2*x;
cout << y << endl;
}
这看起来也没什么,不过我在这里想做到的就是能直接不显示的在循环里将函数写出来,而是在循环外就已经定义好,你可能会觉得,那把方程的计算过程写在函数里,这样也可以,但是为了后面我能写函数数值求导做准备,我不打算这么做。
2.计算图表示方程
有一种东西叫做计算图,可以将计算表达式用图的方式来表达,例如表达。
我在写y = x*x+2*x之后,程序就会自自动生成上面的图,然后我做如下操作就会计算出x=n时候y的值。
Var x = Variable::make_var(0.0);//声明一个变量
Op y = x * x + x;//组合一个表达式
for (int i = 0; i < 10; i++)
{
Variable::set_var(x, i);//给变量设定值
cout << y->forward() << endl;//计算表达式
}
上面代码中有些东西我还没有叙述,但是实际上最后效果就是上面的样子。
3.实现
构建图就需要有图的结点,所以结点类如下。
class OpNode
{
public:
virtual float forward() { return 0; }
};
目前,结点中有加法,乘法,变量,常数,所以我创建这四个基本结构。
//变量X结点
class Variable : public OpNode
{
public:
Variable() {}
Variable(float n):v(n) {}
float v;
static shared_ptr<Variable> make_var(float n) { return make_shared<Variable>(Variable(n)); }
float forward() { return v; }
};
using Var = shared_ptr<Variable>;
//加法结点
class AddNode : public OpNode
{
public:
AddNode(shared_ptr<OpNode> _a, shared_ptr<OpNode> _b) :a(_a), b(_b) {}
shared_ptr<OpNode> a,b;
float forward() { return a->forward() + b->forward(); }
};
//乘法结点
class MulNode : public OpNode
{
public:
MulNode(shared_ptr<OpNode> _a, shared_ptr<OpNode> _b) :a(_a), b(_b) {}
shared_ptr<OpNode> a, b;
float forward() { return a->forward() * b->forward(); }
};
//常数结点
class Constant : public OpNode
{
public:
float v;
Constant() {}
Constant(float n) :v(n) {}
float forward() { return v; }
static shared_ptr<Constant> make_var(float n) { return make_shared<Constant>(Constant(n)); }
};
其中forward函数主要就是计算结果的函数。有了这些结点还不够,还需要有将结点能连接在一起的函数,我以重载运算符为主。
//加法运算符重载,输入两个结点,返回加法结点
shared_ptr<AddNode> operator+(shared_ptr<OpNode> a, shared_ptr<OpNode> b)
{
return make_shared<AddNode>(AddNode(a,b));
}
//乘法运算符重载,输入两个结点,返回乘法结点
shared_ptr<MulNode> operator*(shared_ptr<OpNode> a, shared_ptr<OpNode> b)
{
return make_shared<MulNode>(MulNode(a, b));
}
//输入常数数和结点,返回乘法结点
shared_ptr<MulNode> operator*(float a, shared_ptr<OpNode> b)
{
return make_shared<MulNode>(MulNode(Constant::make_var(a), b));
}
//输入结点和常数,返回乘法结点
shared_ptr<MulNode> operator*(shared_ptr<OpNode> a, float b)
{
return make_shared<MulNode>(MulNode(a, Constant::make_var(b)));
}
有了能连接结点乘图的函数之后,将结点连接在一起。
using Op = shared_ptr<OpNode>;
Op z = x * x*x + x;
创建变量需要创建智能指针类型,设置值的时候也需要单独的函数来赋值,所以在变量类中加入了如下两个函数。
class Variable : public OpNode
{
public:
...
...
static shared_ptr<Variable> make_var(float n) { return make_shared<Variable>(Variable(n)); }
static void set_var(shared_ptr<Variable>& a, float b){a->v = b;}
};
然后最后的总体效果如下。
int main()
{
//声明变量
Var x = Variable::make_var(0.0);
Var y = Variable::make_var(0.0);
//构建表达式
Op z = x * x + x;
//计算并输出结果
for (int i = 0; i < 10; i++)
{
Variable::set_var(x, i);
cout << z->forward() << endl;
}
return 0;
}