关于随机漫步的介绍参见:随机漫步理论
通过cpp实现随机漫步的关系模型。(计算移动目标位移需要随机漫步多少步)
通过实践才能知道自己的不足,仅仅是看书难免会感觉生疏。
下面是实现:
一共3个文件,分别是Vector.h
–> 矢量类定义,Vector.cpp
–>矢量类的具体实现,main.cpp
–>随机漫步模型的具体实现。
//
// Created by cat on 2018/1/1.
//
#ifndef CPP02_STEP_H
#define CPP02_STEP_H
#include <iostream>
#include <cmath>
#include <math.h>
#define Math_PI 3.1415927
/**
* 矢量类
*/
namespace VECTOR {
class Vector {
public:
enum Mode {
/*正坐标*/ RECT,/*极坐标*/ POL
};
private:
Mode currentMode;
double angle; // 角度 (0~360度)
double length; // 步长��(1~3m)
double xLen; // x 方向的位移
double yLen; // y 方向的位移
Vector set2RECT() const; // 转成正坐标
Vector set2POL() const; // 转成级坐标
double radian2Angle(double radian) const // 弧度转角度
{
return 1.0 * radian / Math_PI * 180;
}
double angle2Radian(double angle) const // 角度转弧度
{
return 1.0 * angle * Math_PI / 180;
}
public:
Vector(double num1 = 0, double num2 = 0, Mode currentMode = POL);
Vector(const Vector &data);
double getLength() {
return this->length;
};
virtual ~Vector();
void reset(double num1 = 0, double num2 = 0, Mode currentMode = POL);
// operator
Vector operator*(double factor);
Vector operator*=(double factor);
Vector operator-();
// friend operator
friend std::ostream &operator<<(std::ostream &os, Vector &obj); // toString
friend Vector operator+(const Vector &one, const Vector &another);
friend Vector operator+=(Vector &one, const Vector &another);
friend Vector operator-(const Vector &one, const Vector &another);
friend Vector operator-=(Vector &one, const Vector &another);
friend Vector operator*(double factor, Vector &obj);
friend Vector operator*=(double factor, Vector &obj);
};
}
#endif //CPP02_STEP_H
//
// Created by cat on 2018/1/1.
//
#include "Vector.h"
#include <cmath>
namespace VECTOR {
Vector::Vector(const Vector &data) {
this->xLen = data.xLen;
this->yLen = data.yLen;
this->angle = data.angle;
this->length = data.length;
this->currentMode = data.currentMode;
}
Vector::Vector(double num1,
double num2,
Vector::Mode currentMode) {
reset(num1, num2, currentMode);
}
void Vector::reset(double num1,
double num2,
Vector::Mode currentMode) {
this->currentMode = currentMode;
if (this->currentMode == POL) {
this->angle = num1;
this->length = num2;
this->xLen = sin(radian2Angle(num1)) * num2;
this->yLen = cos(radian2Angle(num1)) * num2;
} else if (this->currentMode == RECT) {
this->xLen = num1;
this->yLen = num2;
this->angle = radian2Angle(atan2(this->yLen, this->xLen));
double len2 = pow(this->xLen, 2) + pow(this->yLen, 2);
this->length = pow(len2, 0.5);
} else {
throw "error!";
}
}
Vector::~Vector() {
this->currentMode = POL;
this->angle = 0;
this->length = 0;
this->xLen = 0;
this->yLen = 0;
}
Vector Vector::set2RECT() const {
Vector v = Vector(*this);
if (this->currentMode == Vector::RECT) {
return v;
} else if (this->currentMode == Vector::POL) {
v.currentMode = Vector::RECT;
v.xLen = this->length * cos(this->angle2Radian(this->angle));
v.yLen = this->length * sin(this->angle2Radian(this->angle));
}
return v;
}
Vector Vector::set2POL() const {
Vector v = Vector(*this);
if (this->currentMode == Vector::POL) {
return v;
} else {
v.currentMode = Vector::POL;
v.angle = radian2Angle(atan2(this->yLen, this->xLen));
double len2 = pow(this->xLen, 2) + pow(this->yLen, 2);
v.length = pow(len2, 0.5);
}
return v;
}
Vector operator+(const Vector &a, const Vector &b) {
Vector obj;
Vector one, another;
one = a.set2RECT();
another = b.set2RECT();
obj = Vector(one.xLen + another.xLen, one.yLen + another.yLen, Vector::RECT);
return obj;
}
Vector VECTOR::operator+=(Vector &one, const Vector &another) {
one = operator+(one, another);
return one;
}
Vector operator-(const Vector &a, const Vector &b) {
Vector one, another;
Vector::Mode mode = one.currentMode;
one = a.set2RECT();
another = b.set2RECT();
Vector v = Vector(one.xLen - another.xLen, one.yLen - another.yLen, Vector::RECT);
v.currentMode = mode;
return v;
}
Vector operator-=(Vector &one, const Vector &another) {
one = operator-(one, another);
return one;
}
Vector Vector::operator*(double factor) {
Vector obj;
Vector::Mode mode = this->currentMode;
this->set2RECT();
obj = Vector(this->xLen * factor, this->yLen * factor, Vector::RECT);
obj.currentMode = mode;
return obj;
}
Vector Vector::operator*=(double factor) {
return operator*(factor);
}
Vector operator*(double factor, Vector &obj) {
return obj * factor;
}
Vector operator*=(double factor, Vector &obj) {
return operator*(factor, obj);
}
Vector Vector::operator-() {
Mode mode = this->currentMode;
this->set2RECT();
Vector v = Vector(-this->xLen, -this->yLen, Vector::RECT);
v.currentMode = mode;
return v;
}
std::ostream &operator<<(std::ostream &os, Vector &obj) {
std::ios_base::fmtflags pref;
std::streamsize preC;
pref = os.setf(std::ios_base::fixed); // store prev
preC = os.precision(1); // store prev
os << "Vector:(" << obj.xLen << " , " << obj.yLen << ")|[RECT]\t";
os.precision(2);
os << "Vector:(" << obj.angle << " , " << obj.length << ")|[POL]\t";
if (obj.currentMode == Vector::RECT) {
os << "{RECT}\n";
} else {
os << "\t{POL}\n";
}
os.setf(pref); // reset
os.precision(preC); // reset
return os;
}
}
#include <iostream>
#include <sstream>
#include <random>
#include <stdlib.h>
#include "Vector.h"
void end();
void resetCin();
void executeFromUser();
void execute(double length, double step);
void executeTimes(unsigned int times);
const unsigned int MAX_FREE = 10;
bool USER_INPUT = false; // 是否每次都让用户输入
static int usedTimes = 0;
static int currentSteps = 0;
int main() {
using namespace std;
using VECTOR::Vector;
Vector v1 = Vector(20, 30, Vector::RECT);
Vector v2 = Vector(40, 50, Vector::RECT);
v1 += v2;
cout << v1 << endl;
// executeFromUser();
executeTimes(100);
return 0;
}
void executeTimes(unsigned int times) {
using namespace std;
using VECTOR::Vector;
cout << "随机漫步模拟.\n";
double avg = 0;
double length; // 总位移
double eachLen;// 单步长度
string input;
stringstream ostr;
cout << "请输入总位移长度(退出请按q):";
getline(cin, input);
ostr << input;
while (1) {
if (ostr >> length) {
cout << "length==" << length;
ostr.clear();
cout << "请输入单步位移长度(退出请按q):";
getline(cin, input);
ostr << input;
if (ostr >> eachLen) {
cout << "todo: SUCCESS\n";
for (int pos = 0; pos < times; ++pos) {
execute(length, eachLen);
avg += currentSteps;
}
goto fuck;
} else {
cout << "输入不合法, 请重新输入!\n";
}
} else {
cout << "输入不合法, 请重新输入!\n";
}
}
fuck:;
avg = avg / times;
streamsize precision = cout.precision(2);
cout << "随机漫步目标位移为" << length << "时的平均步数为:" << avg << "\n";
cout.precision(precision);
}
void execute(double length, double step) {
using namespace std;
using VECTOR::Vector;
Vector init{};
// cout << "init.Length=" << init.getLength() << " , length=" << length << endl;
while (init.getLength() < length) {
currentSteps++;
double angle = random() % 360;
double el = step;
Vector each = Vector(angle, el);
// cout << "........each:" << each;
init += each;
}
streamsize precision = cout.precision(2);
cout << "RESULT:" << init;
cout << "这一次走完目标距离(" << length << ")一共用了[" << currentSteps << "]步,";
cout << "目前距离长度为:" << init.getLength() << " > 目标长度:" << length << endl;
usedTimes++;
cout << "还有(" << (MAX_FREE - usedTimes) << ")次机会\n";
cout.precision(precision);
}
void executeFromUser() {
using namespace std;
using VECTOR::Vector;
cout << "随机漫步模拟.\n";
double length; // 总位移
double eachLen;// 单步长度
string input;
stringstream ostr;
while (usedTimes <= MAX_FREE) {
cout << "请输入总位移长度(退出请按q):";
getline(cin, input);
ostr << input;
if (ostr >> length) {
cout << "length==" << length;
ostr.clear();
cout << "请输入单步位移长度(退出请按q):";
getline(cin, input);
ostr << input;
if (ostr >> eachLen) {
cout << "todo: SUCCESS\n";
execute(length, eachLen);
if (!USER_INPUT) {
goto fuck;
}
} else {
cout << "输入不合法, 请重新输入!\n";
}
} else {
cout << "输入不合法, 请重新输入!\n";
}
}
if (usedTimes > MAX_FREE) {
cout << "体验机会已经用光,继续体验请充值~^_^\n";
}
end();
fuck:;
}
void end() {
resetCin();
std::cout << "Bye.\n";
}
void resetCin() {
std::cin.clear();
while (std::cin.get() != '\n')continue;
}
完整的项目可以参见:随机漫步关系模型cpp实现
当然,这个代码写得不好,没有去优化内存。
可以看一下输出效果:
随机漫步模拟.
请输入总位移长度(退出请按q):100
请输入单步位移长度(退出请按q):1
随机漫步目标位移为100.00时的平均步数为:497246.73
从输出结果可以看到,通过1000次的模拟,得出的平均数是49万步,才能前进100米。(假设步长是固定的,为1米)。
ps: 这个结果也不一定正确,说不定程序逻辑有问题。~