點乘和叉乘及其物理意義(C++STL實現)
一些錯誤觀念的澄清,比如數學意義上的
點積
和叉積
並不對應matlab程式中的.*
(按位相乘)和*
(矩陣乘法)內積的物理意義
- 一種向量到標量的對映
- 兩向量的夾角的計算
- 兩向量是否正交的判斷
- 兩向量的相似性(similarity)的度量
叉積的意義
如何使用C++語言(STL容器,運算子過載):
- 表示向量
- 計算內積
- 計算叉積
- 計算模長
- 計算兩向量的夾角
- 計算點到直線的距離
prerequisites
內積(inner product)
又叫點乘,點積(dot product),數量積,顧名思義得到的是一個標量(scalar)。
- 代數定義
向量
x=[x_1, x_2, \ldots, x_n]
和y=[y_1, y_2, \ldots, y_n]
的內積定義為:
x\cdot y=\sum_i^nx_iy_i=x_1y_1+x_2y_2+\dots+x_ny_n
也即:內積等於向量的對應位相乘再相加,如果從函式的觀點來看的話,即是兩個向量相互作用得到一個標量。
內積對相互作用的兩個向量
x,y x,y的長度也即各自所含元素的個數是沒有限制的。這點不同於向量叉積,叉積所要的向量長度最高為3.
- 幾何定義
歐式空間中,向量是一個同時擁有長度和方向的幾何物件。向量
x
的長度記為\|x\|
,兩個向量的內積定義為:
x\cdot y=\|x\|\|y\|cos\theta
\theta
標識著兩向量的夾角。可見當向量正交時,\theta = 90^\circ
,x\cdot y = 0
。 當向量
y
被歸一化為長度為1的單位向量時,x\cdot y=\|x\|cos\theta
,我們來考察x,y
均為二維的情形:
如上圖所示,此時二者的內積表示的恰是其中一個向另外一個的投影,投影長度越小,說明二者的夾角越大,反之亦然。當兩向量同時歸一化為1時,此時內積的定義為:
x\cdot y = cos\theta
,內積越大,說明兩者夾角越小,也間接地說明兩者也就越相似,故在許多機器學習的演算法,常用餘弦相似性來度量兩特徵向量的逼近程度。內積既然能夠表徵兩向量的夾角,自然判斷兩向量是否正交(值為0)就更不在話下了。
叉積
又叫叉乘(cross product)或者外積,它的計算結果是一個向量而非標量。叉積所在的向量與參與運算的兩個向量都正交,也即正交於原來的兩個向兩邊所決定的平面,也即兩向量所決定的平面的法向量可通過計算叉積的方式得以確定。當參與運算的兩向量是平行的兩個向量時,得到的叉積為0,也即可通過計算叉積的方式判斷兩向量是否平行。
代數定義
- 二維時
x\times y = x_1y_2-x_2y_1
- 三維時
根據如圖的計算方法可得:
\begin{eqnarray}
\begin{split}
\textbf{u}\times \textbf{v}=&
\begin{vmatrix}
\textbf {i} & \textbf{j} & \textbf{k} \\
u_1 & u_2 & u_3 \\
v_1 & v_2 & v_3
\end{vmatrix}\\
=&(u_2v_3\textbf{i}+u_3v_1\textbf{j}+u_1v_2\textbf{k})-(u_3v_2\textbf{i}+u_1v_3\textbf{j}+u_2v_1\textbf{k})\\
=&(u_2v_3-u_3v_2)\textbf{i}+(u_3v_1-u_1v_3)\textbf{j}+(u_1v_2-u_2v_1)\textbf{k}\\
=&(u_2v_3-u_3v_2, u_3v_1-u_1v_3, u_1v_2-u_2v_1)
\end{split}
\end{eqnarray}
幾何定義
x\times y = \|x\|\|y\|sin\theta \vec{n}
\vec{n}
表示叉積方向上的單位向量。
中學知識告訴我們三角形的面積計算公式為:
S=\dfrac{\|x\|\|y\|sin\theta}{2}=\dfrac{\|z\|h}{2}
其中
\theta
表示的是x, y
之間的夾角,由以上兩個公式我們可得到三角形的高
或者點到其所對的邊的距離
,也即點到直線的距離,的計算公式:
h=\|x\times y\|/\|z\|
C++ STL實現
- 向量的定義:
typedef vector<double> Vec;
- 矩陣減法
Vec operator-(const Vec& x, const Vec& y)
{
assert(x.size() == y.size());
// #include <cassert>
Vec tmp;
for(size_t i = 0; i < x.size(); ++i)
tmp.push_back(x[i] - y[i]);
return tmp; // 返回區域性變數的拷貝
}
- 內積和叉積的定義
為了形式的簡單,我們在C++中以*
表示內積,以^
表示叉積,分別對二者進行運算子過載:
double operator*(const Vec& x, const Vec& y)
{
assert(x.size() == y.size()); // #include <cassert>
double sum = 0.;
for (size_t i = 0; i < x.size(); ++i)
sum += x[i]*y[i];
return sum;
}
// 三維的情況
Vec operator^(const Vec& x, const Vec& y)
{
assert(x.size() == y.size() && x.size() == 3);
return Vec{x[1]*y[2]-x[2]*y[1],
x[2]*y[0]-x[0]*y[2],
x[0]*y[1]-x[1]*y[0]};
// uniform initialization, C++11新特性
}
// 二維就姑且返回其模長吧
double twoDCrossProd(const Vec& x, const Vec& y)
{
return x[0]*y[1]-x[1]*y[0];
}
- 模長或者範數的計算
double norm(const Vec& x)
{
double val = 0.;
for(auto elem: x)
val += elem*elem;
return sqrt(val);
// #include <cmath>
}
- 向量夾角的計算
#define PI 3.14159265358979323846
// 弧長向弧度的轉換
double toDegree(double val)
{
return val*180/PI;
}
double angle(const Vec& x, const Vec& y)
{
return toDegree(acos(x*y/norm(x)/norm(y)));
// x*y, 計算二者的內積
}
- 點到直線的距離
// x0, x1, x2 分別表示三角形的三個頂點的座標
// 這裡計算的是點x0到x1和x2構成的直線的距離
double distance(const Vec& x0, const Vec& x1, const Vec& x2)
{
return twoDCrossProd(x1-x0, x2-x0)/norm(x1-x2);
}
客戶端程式:
int main(int, char**)
{
Vec x{1, 0, 0}, y{0, 1, 0};
Vec z = x^y; // 計算叉乘
copy(z.begin(), z.end(), ostream_iterator<double>(cout, " "));
cout << endl;
// 0 0 1
Vec alpha{1, 0}, beta{1, 1};
cout << angle(alpha, beta) << endl;
// 45
Vec x0{0, 0}, x1{1, 0}, x2{0, 1};
cout << distance(x0, x1, x2) << endl;
// 1/sqrt(2)
return 0;
}
相關文章
- 【Unity】向量點乘與叉乘Unity點乘
- Unity向量的演算法:叉乘和叉乘的實戰用法Unity演算法
- 向量點乘為降維,叉乘為升維點乘
- 【數學】向量點乘、叉乘的理論、應用及程式碼實現(C++)點乘C++
- Oracle中實現連乘Oracle
- Oracle中實現連乘(二)Oracle
- c語言實現階乘C語言
- Oracle實現連乘的辦法Oracle
- c#遞迴實現 階乘C#遞迴
- 笛卡爾乘積的javascript版實現和應用JavaScript
- Unity開發中常用的基礎3D數學(向量,點乘,叉乘,矩陣,四元數,尤拉角)Unity3D點乘矩陣
- 三維旋轉矩陣 左乘和右乘分析矩陣
- Oracle SQL實現階乘的幾個方法OracleSQL
- 特徵向量的物理意義特徵
- 遞迴和非遞迴分別實現求n的階乘遞迴
- C++STL::兩種方式實現STL容器的reference語義C++
- PHP 單例模式優點意義及如何實現PHP單例模式
- ECDSA—模乘模組
- 計算階乘
- ACM 階乘之和ACM
- 矩陣連乘矩陣
- 遞迴的列印和階乘運用遞迴
- 定義一個求n的階乘的函式函式
- 攜程假保單事件,聯想到乘意險系統需求事件
- 浮點數表示及其實現.
- CUDA 版本矩陣乘矩陣
- 高精度加減乘
- ASMLib存在的現實意義ASM
- 24. 平衡二叉樹,及其程式碼實現二叉樹
- 乘聯會:關於我國智慧網聯汽車發展現狀及其相關政策的分析
- 數值分析:最小二乘與嶺迴歸(Pytorch實現)PyTorch
- 實踐和思考的重要意義
- 乘聯會:2024年8月全國狹義乘用車零售190.5萬輛 同比下降1.0%
- 乘聯會:2021年11月份全國乘用車市場分析
- 乘聯會:2021年10月份全國乘用車市場分析
- 最小二乘(LS)與總體最小二乘(TLS)總結一TLS
- 人工智慧基礎-範數的物理意義人工智慧
- 理解最小二乘解