我经常需要编码 explicit schemes这意味着我必须通过增加时间变量 t <- t+ dt
来查看函数的演变.因此,让我的循环在 dt
上递增是很自然的:
int N = 7;
double t=0., T = 1., dt=T/N; // or I could have dt=0.03 for example
for(; t<T; t+= dt){
if(T - t < dt){
dt = T-t;
}
//some functions that use dt, t, T etc
}
这背后的基本原理是我递增 t
按常数 dt
在每一步,除了最后一次迭代,如果我当前时间t
是这样的 T- dt < t < T
然后我将我的时间增量修改为 dt <- T-t
.
这种程序可能存在哪些缺陷或我可以改进它的方法是什么?我确实意识到我可能会得到非常小的时间增量。
是否有任何可能出现的 float 问题(我是否应该坚持对整数递增)?
在优化方面,我假设这种技术根本不昂贵,因为基本的分支预测几乎总是会跳过 if
block 。
编辑
我意识到我的问题不是很好。通常是 dt
由 CFL condition 给出即,与其他一些参数相比,它是足够小的。
所以从逻辑上来说,dt
首先给出,然后我们可以定义一个整数 N=floor(T/dt)
, 以整数循环直到 N
,然后处理剩余的时间间隔N*dt --- T
.
代码为:
double dt = //given by some function;
double t=0., T = 1.;
for(; t<T; t+= dt){
if(T - t < dt){
dt = T-t;
}
//some functions that use dt, t, T etc
}
最佳答案
首先补偿if (T - t < dt)
不需要,因为它的唯一目的似乎是将最后一个值设置为 t == T
, 由于不等式将不会被处理 ...;t < T;...
在 for 循环条件下。
也就是说,有限差分法不能很好地处理 float ,除非 N
是二的幂。如果例如人们希望以 0.1f 的步长计算一个函数,很可能会错过一些积分点。
分支预测可能会跳过条件评估,但混合浮点运算和流量控制运算也可能会产生惩罚/延迟。
由于累积舍入误差,优化器可能无法轻易确定迭代计数,从而不允许进行某些优化(循环展开甚至矢量化)。
可以通过线性插值简单地减轻不准确性:t = c * dt;
,但并不完美,因为并非所有情况都适用 (dbl / N) * N == dbl
.在实践中,误差应该在 epsilon 量级。要获得准确的结束值,必须计算 t = (range * N) / N;
这次确保range * N
不会丢弃最低有效位。
关于c++ - 双变量作为循环计数器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31723131/