关于向量
高中数学必修 4 4 4说:
几何向量是线性空间中有大小与方向的量。
放图理解一下:
如上图所示,向量可以形象的用一根箭头表示。箭头所指代表向量的方向,线段的长度代表向量的大小。
在 O I OI OI中,我们简化了一下向量的存储方式及运算法则,我们定义向量为起点为 ( 0 , 0 ) (0,0) (0,0)的一条有方向的线段。由于我们在考虑向量时只考虑其大小与方向,一般不考虑具体位置,故我们将向量平移至坐标系原点处以简化运算。
所以,在之后的讲解中,我们默认向量和点已经被存在了一个结构体里面(向量和点记录的东西都是一个坐标):
struct Point{double x,y; //注意这个double
};
如果想分清楚具体是点还是向量,那么只需要在结构体后加入一句:
typedef Point Vector;
这样我们就可以只开一个结构体而做到存储两种量。
tips:如果您觉得只用Point即可,那么请将后文的Vector全部视为Point(这样写出来也没有任何问题)
向量的运算法则(具体原理请查阅数学必修 4 4 4)
前置:模长
∣ A ∣ |A| ∣A∣表示向量 A A A的长度,为一个数。
double Length(const Vector &p){return sqrt(p.x*p.x+p.y*p.y);
}
前置:向量的方向
(请暂且忽略 B B B以及 β 和 γ \beta和\gamma β和γ,后面要用)
我们设向量 A A A为 ( x , y ) (x,y) (x,y),那么
c o s ( α ) = s i n ( 9 0 。 − α ) = x ∣ A ∣ cos(\alpha)=sin(90^。-\alpha)=\frac{x}{|A|} cos(α)=sin(90。−α)=∣A∣x
s i n ( α ) = c o s ( 9 0 。 − α ) = y ∣ A ∣ sin(\alpha)=cos(90^。-\alpha)=\frac{y}{|A|} sin(α)=cos(90。−α)=∣A∣y
那么,我们定义向量 A A A的方向为 w ( c o s ( α ) , s i n ( α ) ) 。 w(cos(\alpha),sin(\alpha))。 w(cos(α),sin(α))。
点±向量=点
//所有的重载运算符都定义在结构体外部,如果不重载运算符的话会很麻烦
Point operator + (const Point &p,const Vector &q){return (Point){p.x+q.x,p.y+q.y};
}
Point operator - (const Point &p,const Vector &q){return (Point){p.x-q.x,p.y-q.y};
}
点-点=向量
Vector operator - (const Point &p,const Point &q){return (Vector){p.x-q.x,p.y-q.y};
}
友情提示:两个减的操作只需要写一个,如果实在看不顺眼,那么就讲其中一个减号改为另外一个不相冲突的符号。
点+点无意义
向量*常数=向量
Vector operator * (const Vector &p,const double &k){//double很重要!!!return (Vector){p.x*k,p.y*k};
}
向量/常数=向量
Vector operator / (const Vector &p,const double &k){return (Vector){p.x/k,p.y/k};
}
向量±向量=向量
代码同点±向量
向量的点积
令向量 X = ( x 1 , x 2 ) , Y = ( y 1 , y 2 ) , X=(x_1,x_2),Y=(y_1,y_2), X=(x1,x2),Y=(y1,y2),则有:
定义式: X ⋅ Y = ∣ X ∣ ∣ Y ∣ c o s ( γ ) X\cdot Y=|X||Y|cos(\gamma) X⋅Y=∣X∣∣Y∣cos(γ),其中 γ \gamma γ为 X , Y X,Y X,Y的夹角
但更通用的是这样一个式子: X ⋅ Y = ∣ X ∣ ∣ Y ∣ c o s ( γ ) = x 1 y 1 + x 2 y 2 X\cdot Y=|X||Y|cos(\gamma)=x_1y_1+x_2y_2 X⋅Y=∣X∣∣Y∣cos(γ)=x1y1+x2y2
double Dot (const Vector &p,const Vector &q){return p.x*q.x+p.y*q.y;
}
几何意义:A在B所在方向的投影的模长和B的模长的乘积
tips:如果向量 A , B A,B A,B的点积为 0 0 0,则 A , B A,B A,B垂直
证明如下:
我们有上面讲到的向量的方向可知,
c o s ( α ) = x 1 ∣ X ∣ , s i n ( α ) = x 2 ∣ Y ∣ cos(\alpha)=\frac{x_1}{|X|},sin(\alpha)=\frac{x_2}{|Y|} cos(α)=∣X∣x1,sin(α)=∣Y∣x2
c o s ( β ) = y 1 ∣ X ∣ , s i n ( β ) = y 2 ∣ Y ∣ cos(\beta)=\frac{y_1}{|X|},sin(\beta)=\frac{y_2}{|Y|} cos(β)=∣X∣y1,sin(β)=∣Y∣y2
由 γ = α − β \gamma=\alpha-\beta γ=α−β得:
c o s ( γ ) = c o s ( α − β ) cos(\gamma)=cos(\alpha-\beta) cos(γ)=cos(α−β)
由数学必修4上一个著名公式得:
c o s ( γ ) = c o s ( α − β ) = c o s ( β ) c o s ( α ) + s i n ( β ) s i n ( α ) cos(\gamma)=cos(\alpha-\beta)=cos(\beta)cos(\alpha)+sin(\beta)sin(\alpha) cos(γ)=cos(α−β)=cos(β)cos(α)+sin(β)sin(α)
c o s ( γ ) = x 1 ∣ X ∣ × y 1 ∣ Y ∣ + x 2 ∣ X ∣ × y 2 ∣ Y ∣ cos(\gamma)=\frac{x_1}{|X|}\times\frac{y_1}{|Y|}+\frac{x_2}{|X|}\times\frac{y_2}{|Y|} cos(γ)=∣X∣x1×∣Y∣y1+∣X∣x2×∣Y∣y2
c o s ( γ ) = x 1 y 1 + x 2 y 2 ∣ X ∣ ∣ Y ∣ cos(\gamma)=\frac{x_1y_1+x_2y_2}{|X||Y|} cos(γ)=∣X∣∣Y∣x1y1+x2y2
X ⋅ Y = ∣ X ∣ ∣ Y ∣ c o s ( γ ) = x 1 y 1 + x 2 y 2 X\cdot Y=|X||Y|cos(\gamma)=x_1y_1+x_2y_2 X⋅Y=∣X∣∣Y∣cos(γ)=x1y1+x2y2
向量的叉积
定义式: X ∗ Y = ∣ X ∣ ∣ Y ∣ s i n ( γ ) X*Y=|X||Y|sin(\gamma) X∗Y=∣X∣∣Y∣sin(γ)
通用的式子: X ∗ Y = ∣ X ∣ ∣ Y ∣ s i n ( γ ) = x 1 y 2 − x 2 y 1 X*Y=|X||Y|sin(\gamma)=x_1y_2-x_2y_1 X∗Y=∣X∣∣Y∣sin(γ)=x1y2−x2y1
double Cross (const Vector &p,const Vector &q){return p.x*q.y-q.x*p.y;
}
证明大体同上,需要用到另一个著名的式子:
s i n ( α − β ) = s i n ( α ) c o s ( β ) − c o s ( α ) s i n ( β ) sin(α-β)=sin(α)cos(β)-cos(α)sin(β) sin(α−β)=sin(α)cos(β)−cos(α)sin(β)
几何意义:A转到B所夹平行四边形的有向面积
简单地解释一下:
在 A , B A,B A,B不共线的情况下,如果 A A A在 B B B上面,那么它们的叉积就小于 0 , 0, 0,反之则大于 0 0 0。
如果 A , B A,B A,B共线,那么它们的叉积就等于 0 0 0。
基础运算完整代码
struct Point{double x,y;
};
typedef Point Vector;
Point operator + (const Point &p,const Vector &q){return (Point){p.x+q.x,p.y+q.y};
}
Vector operator - (const Point &p,const Point &q){return (Vector){p.x-q.x,p.y-q.y};
}
Vector operator * (const Vector &p,const double &k){return (Vector){p.x*k,p.y*k};
}
Vector operator / (const Vector &p,const double &k){return (Vector){p.x/k,p.y/k};
}
double Dot (const Vector &p,const Vector &q){return p.x*q.x+p.y*q.y;
}
double Cross (const Vector &p,const Vector &q){return p.x*q.y-q.x*p.y;
}
double Length(const Vector &p){return sqrt(Dot(p,p));
}