双变量作为循环计数器

时间:2015-07-30 11:55:27

标签: c++ for-loop floating-point

我经常需要编码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修改我的时间增量。

这种程序有哪些可能的缺陷或我可以改进的方法?我意识到我可能会得到一个非常小的时间增量。

是否存在可能出现的浮动问题(我应该坚持使用整数递增)?

就优化而言,我认为这种技术根本不是昂贵的,因为基本的分支预测几乎总是会跳过if块。

修改

我意识到我的问题并不是很好。通常dtCFL 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
} 

2 个答案:

答案 0 :(得分:0)

首先,根本不需要补偿if (T - t < dt),因为它的唯一目的似乎是将最后一个值设置为t == T,由于不等式...;t < T;...而导致该值不会被处理for loop condition。

话虽如此,除非N是2的幂,否则有限差分方法对浮点数的效果不佳。如果是一个人希望以0.1f的步长评估一个函数,一个人很可能会错过几个积分。

分支预测可能会跳过条件评估,但在使用流控制操作混合浮点运算时可能还会有一个惩罚/延迟。

由于累积舍入误差,优化器无法轻易确定迭代计数,不允许某些优化(循环展开甚至向量化)。

可以简单地通过线性插值来缓解不准确性:t = c * dt;,但不完美,因为并非所有情况(dbl / N) * N == dbl。在实践中,错误应该在 epsilon 幅度中。要获得精确的结束值,必须先计算t = (range * N) / N;,确保range * N不会丢弃最低有效位。

答案 1 :(得分:0)

使用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使用执行必要的计算 每次迭代都需要tTdt。 必须由函数更新的数据可以成为成员 类的变量或可以包含在函数参数中 列为非const引用。

顺便说一句,我最后一次调用循环外的函数而不是 为了节省分支条件的可能成本,但是因为 我发现代码组织得更好,更容易理解。

旧答案:

如你所说,最后你可以轻松获得非常小的时间增量 因为结果T/N通常不准确 (而0.03肯定不确切。)

我更愿意像这样开发tdt

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.
}

(请注意,如果您决定以非{0}的{0}值开始迭代,则会显示dt = (T - t)/N

或者,如果t非常大,可能会稍微准确一些 (因为只要N变得更大,t += dt就会有效地完成dt

t