本文章是作者根据史蒂芬·普拉达所著的《C++ Primer Plus》而整理出的读书笔记,如果您在浏览过程中发现了什么错误,烦请告知。另外,此书由浅入深,非常适合有C语言基础的人学习,感兴趣的朋友可以自行阅读此书籍。
矢量,是工程和物理中使用的一个术语,它是一个有大小和方向的量。例如,推东西时,推的效果将取决于推力的大小和推的方向。
同时,矢量也支持相加,首先,画一个矢量,然后从第一个矢量的尾部开始画第二个矢量。最后从第一个矢量的开始处向第二个矢量的结尾处画一个矢量。第三个矢量表示前两个矢量的和。注意,两个矢量之和的长度可能小于它们的长度之和。
显然无法使用一个数来表示矢量,因此应创建一个类来表示矢量。其次,矢量与普通数学运算有相似之处,因此应重载运算符。
出于简化的目的,本节将实现一个二维矢量(如屏幕位移)。描述二维矢量只需要两个数,但可以选择到底使用哪两个数:
- 可以用大小(长度)和方向(角度)描述矢量;
- 可以用分量x和y表示矢量。
两个分量分别是水平矢量(x分量)和垂直矢量(y分量),将其相加可以得到最终的矢量。例如,可以这样描述点的运动:向右移动30个单位,再向上移动40个单位。这将把该点沿与水平方向呈53.1度的方向移动50个单位(没错,就是勾股定理),因此,水平分量为30个单位、垂直分量为40个单位的矢量,与长度为50个单位、方向为53.1度的矢量相同。
因此在设计这个类时,当用户修改了矢量的一种表示时,对象将自动更新另一种表示。
以下是类声明的代码:
//vect.hpp
#ifndef _VECTOR_H_
#define _VECTOR_H_
#include <iostream>
namespace VECTOR
{
class Vector
{
public:
enum Mode{RECT, POL};
private:
double x;
double y;
double mag;
double ang;
Mode mode;
void set_mag();
void set_ang();
void set_x();
void set_y();
public:
Vector();
Vector(double n1, double n2, Mode form = RECT);
void reset(double n1, double n2, Mode form = RECT);
~Vector();
double xval() const {return x;}
double yval() const {return x;}
double magval() const {return mag;}
double angval() const {return ang;}
void polar_mode();
void rect_mode();
Vector operator+(const Vector& b) const;
Vector operator-(const Vector& b) const;
Vector operator-() const;
Vector operator* (double n) const;
friend Vector operator*(double n, const Vector& a);
friend std::ostream & operator<<(std::ostream & os, const Vector& v);
};
}//end namespace VECTOR
#endif
以下类实现代码:
//vect.cpp
#include "cmath"
#include "vect.hpp"
using std::sqrt;
using std::sin;
using std::cos;
using std::atan;
using std::atan2;
using std::cout;
using std::endl;
namespace VECTOR
{
const double Rad_to_deg = 45.0 / atan(1.0);
void Vector::set_mag()
{
mag = sqrt(x * x + y * y);
}
void Vector::set_ang()
{
if (x == 0.0 && y == 0.0)
ang = 0.0;
else
ang = atan2(y, x);
}
void Vector::set_x()
{
x = mag * cos(ang);
}
void Vector::set_y()
{
y = mag * sin(ang);
}
Vector::Vector()
{
x = y = mag = ang = 0.0;
mode = RECT;
}
Vector::Vector(double n1, double n2, Mode form)
{
mode = form;
if(form == RECT)
{
x = n1;
y = n2;
set_mag();
set_ang();
}
else if (form == POL)
{
mag = n1;
ang = n2 / Rad_to_deg;
set_x();
set_y();
}
else{
cout << "Incorrect 3rd argument to Vector() --";
cout << "vector set to 0\n";
x = y = mag = ang = 0.0;
mode = RECT;
}
}
void Vector::reset(double n1, double n2, Mode form)
{
mode = form;
if(form == RECT)
{
x = n1;
y = n2;
set_mag();
set_ang();
}
else if (form == POL)
{
mag = n1;
ang = n2 / Rad_to_deg;
set_x();
set_y();
}
else{
cout << "Incorrect 3rd argument to Vector() --";
cout << "vector set to 0\n";
x = y = mag = ang = 0.0;
mode = RECT;
}
}
Vector::~Vector()
{
}
void Vector::polar_mode()
{
mode = POL;
}
void Vector::rect_mode()
{
mode = RECT;
}
Vector Vector::operator+(const Vector& b) const
{
return Vector(x + b.x, y + b.y); //看似只处理了直角坐标,实际上构造函数中会实时更新极坐标
}
Vector Vector::operator-(const Vector& b) const
{
return Vector(x - b.x, y - b.y);
}
Vector Vector::operator-() const
{
return Vector(-x, -y);
}
Vector Vector::operator* (double n) const
{
return Vector(n * x, n * y);
}
Vector operator*(double n, const Vector& a)
{
return a * n;
}
std::ostream & operator<<(std::ostream & os, const Vector& v)
{
if (v.mode == Vector::RECT)
{
os << "(x, y) = (" << v.x << ", " << v.y << ")";
}
else if(v.mode == Vector::POL)
{
os << "(m, a) = (" << v.mag << ", " << v.ang * Rad_to_deg << ")";
}
else
{
os << "Vector object mode is invalid";
}
return os;
}
}//end namespace VECTOR
可以使用Vector类来模拟随机漫步问题:
随机漫步问题,指的是,将一个人领到街灯柱下。这个人开始走动,但每一步的方向都是随机的(与前一步不同)。这个问题的一种表述是,这个人走到离灯柱50英尺处需要多少步。
#include <iostream>
#include <cstdlib>
#include <ctime>
#include "vect.hpp"
int main()
{
using namespace std;
using VECTOR::Vector;
srand(time(0));
double direction;
Vector step;
Vector result(0.0, 0.0);
unsigned long steps = 0;
double target;
double dstep;
cout << "请输入目标距离(按任意字母退出): ";
while (cin >> target)
{
cout << "输入步长:";
if (!(cin >> dstep))
{
break;
}
while (result.magval() < target)
{
direction = rand() % 360;
step.reset(dstep, direction, Vector::POL); //新的一步,新的方向
result = result + step;
steps ++ ;
}
cout << "走了" << steps << "步后,当前位置:\n";
cout << result << endl;
result.polar_mode();
cout << "or\n" << result << endl;
cout << "平均每步向外距离 = "
<< result.magval()/steps << endl;
steps = 0;
result.reset(0.0, 0.0);
cout << "请输入目标距离(按任意字母退出): ";
}
cout << "Bye!\n";
cin.clear();
while (cin.get() != '\n')
{
continue;
}
return 0;
}
程序运行结果如下:
请输入目标距离(按任意字母退出): 50
输入步长:1
走了3553步后,当前位置:
(x, y) = (28.9761, -41.0075)
or
(m, a) = (50.2118, -54.7547)
平均每步向外距离 = 0.0141322
请输入目标距离(按任意字母退出): 50
输入步长:2
走了934步后,当前位置:
(x, y) = (10.1108, -49.3875)
or
(m, a) = (50.4119, -78.43)
平均每步向外距离 = 0.0539742
请输入目标距离(按任意字母退出): 50
输入步长:1
走了1262步后,当前位置:
(x, y) = (-33.2925, -38.2832)
or
(m, a) = (50.7345, -131.011)
平均每步向外距离 = 0.0402017
请输入目标距离(按任意字母退出): q
Bye!
原书中有这么一句话写得很好:
如果发现自己在随机漫步时,请保持自信,迈大步走。虽然在蜿蜒前进的过程中仍旧无法控制前进的方向,但至少会走得远一点。
加油!
标签:11,set,const,double,矢量,再谈,Vector,重载,ang From: https://www.cnblogs.com/superbmc/p/18111865