如何让我的递归函数在进入下一级循环之前读取每个新实例?
How do I make my recursive function read every new instance before proceeding to the next level of the loop?
我必须模拟粒子分裂成粒子。
我的模拟函数决定有多少粒子从分裂中脱落。
然后根据它决定分裂成多少个粒子调用自己进行模拟。
代码如下:
void Reaction::Simulate(double energy, TwoVector position )
{
int RandomNumber= qrand() %3+1;//starting particle
energy = energy/RandomNumber; // change energy for each reaction
double time=1.0;
std::cout<<RandomNumber<<std::endl;
if (RandomNumber==1){
LightParticle* i=new LightParticle(energy, position);
int speed = 3;
i->SimulatePath(time, speed, i->GetPosition());
i->GetPosition().Print();
energy--;
Simulate(energy, i->GetPosition());
}
else if (RandomNumber==2){
MediumParticle* j=new MediumParticle(energy, position);
MediumParticle* k=new MediumParticle(energy, position);
int speed = 2;
j->SimulatePath(time,speed, position);
k->SimulatePath(time,speed, position);
j->GetPosition().Print();
k->GetPosition().Print();
Simulate(energy, j->GetPosition());
Simulate(energy, k->GetPosition());
}
else if (RandomNumber==3) {
HeavyParticle* l = new HeavyParticle(energy, position);
HeavyParticle* m = new HeavyParticle(energy, position);
HeavyParticle* n = new HeavyParticle(energy, position);
int speed = 1;
l->SimulatePath(time,speed, position);
l->GetPosition().Print();
m->SimulatePath(time,speed, position);
m->GetPosition().Print();
n->SimulatePath(time,speed, position);
n->GetPosition().Print();
Simulate(energy, l->GetPosition());
Simulate(energy, m->GetPosition());
Simulate(energy, n->GetPosition());
}
else return;
}
从代码中可以看出,它只会走到一条路径的最深层,然后才会移动到下一条路径。我怎样才能让它同时遵循每条路径?
qsrand()
在未使用值初始化时将始终保持相同的值。
qsrand(time(NULL));
ID=qrand() % 3;
qDebug << “ID random: “ << ID;
或
qsrand(static_cast<quint64>(QTime::currentTime().msecsSinceStartOfDay()));
array<int, 3> arr = {qrand(), qrand(), qrand()};
for(auto i : arr)
cout << i << endl;
我不知道你是否真的想同时走所有的路。在我看来,问题在于打破循环。这应该像
一样提供
void Reaction::Simulate(double energy, TwoVector position )
{
if (energy < minimalEnergy) return;
if (isAtGround(position)) return;
int RandomNumber= qrand() %3+1;//starting particle
// all the rest, but please repair the memory leaks!
}
当你的粒子不能进一步分裂时,你应该提供一个函数 bool isAtGround(const TwoVector& position)
和一个 minimalEnergy
(典型的限制是最轻的粒子质量)。如果能量太小,您可能不会返回,而是沿着粒子路径到达地面。但这取决于你的具体任务。
顺便说一句,我觉得能量只在 RandomNumber==1
期间降低了,这对我来说似乎很奇怪。
首先,使用此代码,您将几乎立即发生堆栈溢出。
您的基本代码路径在伪代码中如下所示:
func() {
path = RAND(1, 3);
if(path == 1) /*DO STUFF*/ func();
else if(path == 2) /*DO STUFF*/ func();
else /*DO STUFF*/ func();
}
因此,无论这些步骤是否 "simultaneous",您的代码永远不会终止。如果您希望代码最终停止,您应该让随机数处于不仅输出数字 [1, 3]
.
的范围内
int RandomNumber= qrand() %4; //Will stop when RandomNumber == 0
如果有更明确的递归停止条件(例如 energy == 0
时),您需要编写代码。
您的第二个问题是您不清楚执行所有这些步骤的意思"simultaneously"。您是否希望所有路径在多个线程中并行执行?
你需要这样写:
std::thread t1([=]{
LightParticle* i=new LightParticle(energy, position);
int speed = 3;
i->SimulatePath(time, speed, i->GetPosition());
i->GetPosition().Print();
energy--;
if(condition_to_continue_recursing()) {
Simulate(energy, i->GetPosition());
}
});
std::thread t2([=]{
MediumParticle* j=new MediumParticle(energy, position);
MediumParticle* k=new MediumParticle(energy, position);
int speed = 2;
j->SimulatePath(time,speed, position);
k->SimulatePath(time,speed, position);
j->GetPosition().Print();
k->GetPosition().Print();
if(condition_to_continue_recursing()) {
Simulate(energy, j->GetPosition());
Simulate(energy, k->GetPosition());
}
});
std::thread t3([=]{
HeavyParticle* l = new HeavyParticle(energy, position);
HeavyParticle* m = new HeavyParticle(energy, position);
HeavyParticle* n = new HeavyParticle(energy, position);
int speed = 1;
l->SimulatePath(time,speed, position);
l->GetPosition().Print();
m->SimulatePath(time,speed, position);
m->GetPosition().Print();
n->SimulatePath(time,speed, position);
n->GetPosition().Print();
if(condition_to_continue_recursing()) {
Simulate(energy, l->GetPosition());
Simulate(energy, m->GetPosition());
Simulate(energy, n->GetPosition());
}
});
t1.join();
t2.join();
t3.join();
但是condition_to_continue_recursing()
是什么就得由你来决定了;我对您的总体任务了解不多,无法回答这个问题。此外,如果您的 condition_to_continue_recursing
非常重要,这将产生荒谬数量的线程;使用线程池可能是首选。所有这一切都取决于您决定使用线程是完成此类任务的理想选择,但(对我而言)这并不明显。
你的第三个问题是这个代码片段中充斥着相当严重的设计错误。
HeavyParticle* l = new HeavyParticle(energy, position);
HeavyParticle* m = new HeavyParticle(energy, position);
HeavyParticle* n = new HeavyParticle(energy, position);
这些指针中的每一个都会泄漏。由于对象仅在定义它们的范围内使用,因此使用 std::unique_ptr
可能是理想的:
std::unique_ptr<HeavyParticle> l = std::make_unique<HeavyParticle>(energy, position);
std::unique_ptr<HeavyParticle> m = std::make_unique<HeavyParticle>(energy, position);
std::unique_ptr<HeavyParticle> n = std::make_unique<HeavyParticle>(energy, position);
编辑:或者,没有充分的理由让您一开始就应该在这种情况下使用指针。以下代码可以完美运行,没有内存泄漏或更改代码的功能:
HeavyParticle l(energy, position);
HeavyParticle m(energy, position);
HeavyParticle n(energy, position);
int speed = 1;
l.SimulatePath(time,speed, position);
l.GetPosition().Print();
m.SimulatePath(time,speed, position);
m.GetPosition().Print();
n.SimulatePath(time,speed, position);
n.GetPosition().Print();
Simulate(energy, l.GetPosition());
Simulate(energy, m.GetPosition());
Simulate(energy, n.GetPosition());
您可能也不应该使用 qrand
。
std::default_random_engine engine(std::random_device()());
void Reaction::Simulate(double energy, TwoVector position )
{
std::uniform_int_distribution<int> distribution(0, 3);
int RandomNumber = distribution(engine);
/*... Whatever*/
更好的设计是将引擎传递给函数。
选择:
std::default_random_engine engine(std::random_device()());
void Reaction::Simulate(double energy, TwoVector position )
{
if(energy <= 0) return;
std::uniform_int_distribution<int> distribution(1, 3);
int RandomNumber = distribution(engine);
/*... Whatever*/
这还有很多内容,但还有很多内容需要深入研究。希望这会是一个好的起点。
我必须模拟粒子分裂成粒子。 我的模拟函数决定有多少粒子从分裂中脱落。 然后根据它决定分裂成多少个粒子调用自己进行模拟。
代码如下:
void Reaction::Simulate(double energy, TwoVector position )
{
int RandomNumber= qrand() %3+1;//starting particle
energy = energy/RandomNumber; // change energy for each reaction
double time=1.0;
std::cout<<RandomNumber<<std::endl;
if (RandomNumber==1){
LightParticle* i=new LightParticle(energy, position);
int speed = 3;
i->SimulatePath(time, speed, i->GetPosition());
i->GetPosition().Print();
energy--;
Simulate(energy, i->GetPosition());
}
else if (RandomNumber==2){
MediumParticle* j=new MediumParticle(energy, position);
MediumParticle* k=new MediumParticle(energy, position);
int speed = 2;
j->SimulatePath(time,speed, position);
k->SimulatePath(time,speed, position);
j->GetPosition().Print();
k->GetPosition().Print();
Simulate(energy, j->GetPosition());
Simulate(energy, k->GetPosition());
}
else if (RandomNumber==3) {
HeavyParticle* l = new HeavyParticle(energy, position);
HeavyParticle* m = new HeavyParticle(energy, position);
HeavyParticle* n = new HeavyParticle(energy, position);
int speed = 1;
l->SimulatePath(time,speed, position);
l->GetPosition().Print();
m->SimulatePath(time,speed, position);
m->GetPosition().Print();
n->SimulatePath(time,speed, position);
n->GetPosition().Print();
Simulate(energy, l->GetPosition());
Simulate(energy, m->GetPosition());
Simulate(energy, n->GetPosition());
}
else return;
}
从代码中可以看出,它只会走到一条路径的最深层,然后才会移动到下一条路径。我怎样才能让它同时遵循每条路径?
qsrand()
在未使用值初始化时将始终保持相同的值。
qsrand(time(NULL));
ID=qrand() % 3;
qDebug << “ID random: “ << ID;
或
qsrand(static_cast<quint64>(QTime::currentTime().msecsSinceStartOfDay()));
array<int, 3> arr = {qrand(), qrand(), qrand()};
for(auto i : arr)
cout << i << endl;
我不知道你是否真的想同时走所有的路。在我看来,问题在于打破循环。这应该像
一样提供void Reaction::Simulate(double energy, TwoVector position )
{
if (energy < minimalEnergy) return;
if (isAtGround(position)) return;
int RandomNumber= qrand() %3+1;//starting particle
// all the rest, but please repair the memory leaks!
}
当你的粒子不能进一步分裂时,你应该提供一个函数 bool isAtGround(const TwoVector& position)
和一个 minimalEnergy
(典型的限制是最轻的粒子质量)。如果能量太小,您可能不会返回,而是沿着粒子路径到达地面。但这取决于你的具体任务。
顺便说一句,我觉得能量只在 RandomNumber==1
期间降低了,这对我来说似乎很奇怪。
首先,使用此代码,您将几乎立即发生堆栈溢出。
您的基本代码路径在伪代码中如下所示:
func() {
path = RAND(1, 3);
if(path == 1) /*DO STUFF*/ func();
else if(path == 2) /*DO STUFF*/ func();
else /*DO STUFF*/ func();
}
因此,无论这些步骤是否 "simultaneous",您的代码永远不会终止。如果您希望代码最终停止,您应该让随机数处于不仅输出数字 [1, 3]
.
int RandomNumber= qrand() %4; //Will stop when RandomNumber == 0
如果有更明确的递归停止条件(例如 energy == 0
时),您需要编写代码。
您的第二个问题是您不清楚执行所有这些步骤的意思"simultaneously"。您是否希望所有路径在多个线程中并行执行?
你需要这样写:
std::thread t1([=]{
LightParticle* i=new LightParticle(energy, position);
int speed = 3;
i->SimulatePath(time, speed, i->GetPosition());
i->GetPosition().Print();
energy--;
if(condition_to_continue_recursing()) {
Simulate(energy, i->GetPosition());
}
});
std::thread t2([=]{
MediumParticle* j=new MediumParticle(energy, position);
MediumParticle* k=new MediumParticle(energy, position);
int speed = 2;
j->SimulatePath(time,speed, position);
k->SimulatePath(time,speed, position);
j->GetPosition().Print();
k->GetPosition().Print();
if(condition_to_continue_recursing()) {
Simulate(energy, j->GetPosition());
Simulate(energy, k->GetPosition());
}
});
std::thread t3([=]{
HeavyParticle* l = new HeavyParticle(energy, position);
HeavyParticle* m = new HeavyParticle(energy, position);
HeavyParticle* n = new HeavyParticle(energy, position);
int speed = 1;
l->SimulatePath(time,speed, position);
l->GetPosition().Print();
m->SimulatePath(time,speed, position);
m->GetPosition().Print();
n->SimulatePath(time,speed, position);
n->GetPosition().Print();
if(condition_to_continue_recursing()) {
Simulate(energy, l->GetPosition());
Simulate(energy, m->GetPosition());
Simulate(energy, n->GetPosition());
}
});
t1.join();
t2.join();
t3.join();
但是condition_to_continue_recursing()
是什么就得由你来决定了;我对您的总体任务了解不多,无法回答这个问题。此外,如果您的 condition_to_continue_recursing
非常重要,这将产生荒谬数量的线程;使用线程池可能是首选。所有这一切都取决于您决定使用线程是完成此类任务的理想选择,但(对我而言)这并不明显。
你的第三个问题是这个代码片段中充斥着相当严重的设计错误。
HeavyParticle* l = new HeavyParticle(energy, position);
HeavyParticle* m = new HeavyParticle(energy, position);
HeavyParticle* n = new HeavyParticle(energy, position);
这些指针中的每一个都会泄漏。由于对象仅在定义它们的范围内使用,因此使用 std::unique_ptr
可能是理想的:
std::unique_ptr<HeavyParticle> l = std::make_unique<HeavyParticle>(energy, position);
std::unique_ptr<HeavyParticle> m = std::make_unique<HeavyParticle>(energy, position);
std::unique_ptr<HeavyParticle> n = std::make_unique<HeavyParticle>(energy, position);
编辑:或者,没有充分的理由让您一开始就应该在这种情况下使用指针。以下代码可以完美运行,没有内存泄漏或更改代码的功能:
HeavyParticle l(energy, position);
HeavyParticle m(energy, position);
HeavyParticle n(energy, position);
int speed = 1;
l.SimulatePath(time,speed, position);
l.GetPosition().Print();
m.SimulatePath(time,speed, position);
m.GetPosition().Print();
n.SimulatePath(time,speed, position);
n.GetPosition().Print();
Simulate(energy, l.GetPosition());
Simulate(energy, m.GetPosition());
Simulate(energy, n.GetPosition());
您可能也不应该使用 qrand
。
std::default_random_engine engine(std::random_device()());
void Reaction::Simulate(double energy, TwoVector position )
{
std::uniform_int_distribution<int> distribution(0, 3);
int RandomNumber = distribution(engine);
/*... Whatever*/
更好的设计是将引擎传递给函数。
选择:
std::default_random_engine engine(std::random_device()());
void Reaction::Simulate(double energy, TwoVector position )
{
if(energy <= 0) return;
std::uniform_int_distribution<int> distribution(1, 3);
int RandomNumber = distribution(engine);
/*... Whatever*/
这还有很多内容,但还有很多内容需要深入研究。希望这会是一个好的起点。