我必须模拟粒子 split 成粒子。 我的模拟函数决定有多少粒子从 split 中脱落。 然后根据它决定 split 成多少个粒子调用自己进行模拟。
代码如下:
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;
}
正如您从代码中看到的那样,在移动到下一条路径之前,它只会到达一条路径的最深层。我怎样才能让它同时遵循每条路径?
最佳答案
首先,这段代码几乎会立即导致堆栈溢出。
您的基本代码路径在伪代码中如下所示:
func() {
path = RAND(1, 3);
if(path == 1) /*DO STUFF*/ func();
else if(path == 2) /*DO STUFF*/ func();
else /*DO STUFF*/ func();
}
因此,无论这些步骤是否“同时”进行,您的代码都永远不会终止。如果你希望代码最终停止,你应该让随机数在一个范围内,而不是只输出数字 [1, 3]
。
int RandomNumber= qrand() %4; //Will stop when RandomNumber == 0
如果递归应该停止的时间有更明确的条件(比如当 energy == 0
时),您需要将其写入代码。
您的第二个问题是您不清楚“同时”执行所有这些步骤的意思。您是否希望所有路径在多个线程中并行执行?
你需要这样写:
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*/
还有很多内容,但还有很多内容需要深入挖掘。希望这将提供一个良好的起点。
关于c++ - 如何让我的递归函数在进入下一级循环之前读取每个新实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41577469/