【发布时间】:2011-06-22 14:55:46
【问题描述】:
我在 Java 中有以下内容,它基本上是一个嵌套的三角形循环:
int n = 10;
B bs[] = new B[n];
// some initial values, bla bla
double dt = 0.001;
for (int i = 0; i < n; i++) {
bs[i] = new B();
bs[i].x = i * 0.5;
bs[i].v = i * 2.5;
bs[i].m = i * 5.5;
}
for (int i = 0; i < n; i++) {
for (int j = **(i+1)**; j < n; j++) {
double d = bs[i].x - bs[j].x;
double sqr = d * d + 0.01;
double dist = Math.sqrt(sqr);
double mag = dt / (sqr * dist);
bs[i].v -= d * bs[j].m * mag;
**bs[j].v += d * bs[i].m * mag;**
}
}
// printing out the value v
for (int i = 0; i < n; i++) {
System.out.println(bs[i].v);
}
B类:
class B {
double x, v, m;
}
在每次迭代中,数组的索引 i 和 j 处的值同时更新,从而避免进行完整的嵌套循环。以下给出了相同的结果,但它执行了一个完整的嵌套循环(请原谅我使用的术语,它们可能不正确,但我希望它确实有意义)。
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
double d = bs[i].x - bs[j].x;
double sqr = d * d + 0.01;
double dist = Math.sqrt(sqr);
double mag = dt / (sqr * dist);
bs[i].v -= d * bs[j].m * mag;
}
}
注意:
与之前代码的唯一变化是int j = 0; NOT int j = (i+1); 并删除了bs[j].v += d * bs[i].m * mag;
我想在 Haskell 中做同样的事情,但很难正确地思考它。我有以下代码。 Haskell 版本中的数组表示为一个列表 (xs),我已将其初始化为 0。
n = 20
xs = replicate n 0
update = foldl' (update') xs [0..(n-1)]
where
update' i = update'' i (i+1) []
update'' i j acc
| j == n = acc
| otherwise = new_acc
where
new_acc = result:acc
result = ...do something
我将对 n 有很大的价值,例如1000、5000 等
当 n = 1000 时,完整的嵌套循环给出 length [(i,j)|i<-[0..1000],j<-[0..1000]] = 1002001,但三角形版本给出 length [(i,j)|i<-[0..1000],j<-[(i+1)..1000]]
= 500500。在 Haskell 中做 2 个地图很容易让它完成完整的循环,但我想要三角形版本。我想这意味着将对 i 和 j 的更改保留在一个列表中,然后在最后更新原始列表?任何想法将不胜感激。谢谢
【问题讨论】:
-
如果你解释一下
update_i和update_j的作用,以及result是什么,我认为会有所帮助,否则不清楚如何最好地写出你想要的。 -
@HaskellElephant:我删除了 2 个方法并将代码放入其中。通过删除不必要的代码,我已经简化了很多。你可以用任何值替换
dt,没关系。谢谢 -
@HaskellElephant:你确定你的两个循环实际上做同样的事情吗?毕竟,循环可能会读取已经更新的值
arr。 -
您提供的两个循环并不等效,因此很难分析您要执行的操作。查看C code snippet。我知道您的代码是用 Java 编写的,但 Java 不是键盘的选项。
-
@HaskellElephant,Anupam:你是对的,代码没有给出相同的结果。我的错。我只是想简化我的代码,但现在代码更完整了,如果你检查一下,两个循环都会给出相同的结果,除了第一个是“三角形”循环,而第二个是完整的嵌套循环。跨度>
标签: haskell