双变量作为循环计数器
Double variable as loop counter
我经常需要编写显式方案,这意味着我必须通过增加时间变量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
。
这种程序可能存在哪些陷阱,或者我可以改进它的方法是什么?我确实意识到我可能会得到一个很小的时间增量。
是否存在可能出现的浮动问题(我应该坚持整数递增吗(?
在优化方面,我认为这种技术根本不昂贵,因为基本分支预测几乎总是跳过if
块。
编辑
我意识到我的问题不是很好。通常,dt
是由CFL条件给出的,即,与一些其他参数相比,它足够小。
因此,从逻辑的角度来看,首先给出了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
,由于for循环条件中的不等式...;t < T;...
,因此不会处理该值。
也就是说,除非N
是2的幂,否则有限差分法在浮点运算中效果不佳。例如,如果希望以0.1f的步长评估函数,则很可能会错过几个积分点。
分支预测可以跳过条件评估,但是在将浮点操作与流控制操作混合时也可能存在惩罚/延迟。
由于累积的舍入误差,优化器可能无法轻松确定迭代次数,从而不允许进行某些优化(循环展开甚至矢量化(。
通过线性插值t = c * dt;
可以简单地减轻误差,但并不完全,因为并非所有情况都是(dbl / N) * N == dbl
。在实践中,误差应在ε幅度内。为了获得确切的结束值,必须计算t = (range * N) / N;
,以确保range * N
不会丢失最低有效位。
有了新信息,dt
必须设置为固定的预定值(至少对于除最后一步外的所有步骤(,以下是我的建议:
double T0 = 0.0;
double T = 1.0;
int N = floor((T - T0)/dt);
double t = T0;
for (int step_number = 0; step_number < N; ++step_number, t += dt)
{
t = T0 + step_number * dt;
do_one_step(t, T, dt);
}
if (t < T)
{
do_one_step(t, T, T - t);
}
函数do_one_step
使用t
、T
和dt
。函数必须更新的数据可以成为成员类的变量或可以包含在函数参数中列为非常数引用。
顺便说一句,我有最后一次调用循环外的函数,而不是为了节省分支条件的可能成本,但因为我发现这样代码组织得更好,更容易理解。
老答案:
你可以很容易地在最后得到一个非常小的时间增量,正如你所说,因为结果CCD_ 27通常不精确(0.03
当然不准确(。
我更喜欢这样开发t
和dt
:
int N = 7;
double t = 0.0;
double T = 1.0;
double dt = (T - t)/N;
for (int step_number = 0; step_number < N; ++step_number, t += dt)
{
// ... calculations with t, T, dt, etc.
}
(请注意,上面写着dt = (T - t)/N
,以防您决定以非零值t
开始迭代。(
或者,如果N
非常大,可能会稍微准确一点(因为一旦t
变得更大,t += dt
就必须有效地将dt
取整(:
int N = 7;
double T = 1.0;
double dt = T/N;
for (int step_number = 0; step_number < N; ++step_number)
{
double t = T0 + step_number * dt;
// ... calculations with t, T, dt, etc.
}
- 循环在计数器中不起作用
- C++ 在循环中添加计数器变量并再次初始化其值
- 几乎总是自动和带计数器的循环
- 为什么使用 2 个嵌套循环 O(n^2) 复杂度来解决二和问题,当只改变循环计数器逻辑时运行得更快?
- 对于循环计数器不递增
- 如何在C++中创建 2d 数组,其中一部分包含循环计数器,另一部分包含数字列表?
- 当输出达到某个值时,如何在 c++ 中中断计数器循环
- 如何在C++中使用带有"do while"循环的计数器?
- 而循环计数器不递增
- 在 Rust 中捕获循环计数器副本的函数
- 为什么它不是一个不确定的循环,因为循环计数器在整数变量的范围之外
- 增加OpenMP中用于进度报告的共享循环计数器
- 用于循环计数器失败的 C++
- For 循环是覆盖循环计数器
- 通过引用将循环计数器或范围声明传递给线程有什么区别
- 使用迭代或简单的循环计数器,哪个更快
- 是否可以打印出与循环计数器相对应的字符串
- 双变量作为循环计数器
- 在循环计数器上缺少警告
- 如何在多线程中同步"for"循环计数器?