我有一个问题,现在我有一个包含300万条记录的列表,我希望得到每两条记录之间的所有差值。一个简单的嵌套循环可能需要永远。有人能建议我能解决这个问题吗?
答案 0 :(得分:5)
如果要计算所有绝对差异的平均值并对时间戳进行排序,则只需要一个循环:
t[i] <= t[i + 1] --> abs(t[i] - t[j]) = t[j] - t[i] for i < j
也就是说,对于每个N
时间戳差异,存在带有正号的加数和带有负号的另一个加数。让我们看一个有4个时间戳的例子:
sum = (t[3] - t[2]) + (t[3] - t[1]) + (t[3] - t[0])
+ (t[2] - t[1]) + (t[2] - t[0])
+ (t[1] - t[0])
此处,t[3]
总是被添加,t[2]
被添加两次并减去一次,t[1]
被添加一次并减去两次,最后最低值t[0]
总是减去。
矿石,更一般:第一个时间戳,即具有最低值的时间戳,始终为负号,N - 1
次。第二个具有N - 2
次负号并且一次为正号,即在比较第一个时间戳时。第三次有N - 3
次负号和正号两次。
所以你的循环是这样的:
sum = 0;
for i = 0 to N:
sum = sum + (2*i - N + 1) * t[i]
其中i
是从零开始的索引而N
是独占上限,C风格。要获得平均值,除以(N - 1) * N / 2
。
如果你的数组没有排序,你必须先对它进行排序,这通常比二次时间具有更好的性能,所以你应该比使用嵌套循环更好。
可能发生的一件事是,通过总结大值,您可以达到数据类型的极限。您可以尝试通过将循环减半并从两端开始求和来解决这个问题,希望差异可以取消。或者你可以除以循环内部的差异总数,可能会引入一些讨厌的浮点舍入错误。
答案 1 :(得分:2)
您可以通过将文件拆分为8个块并同时处理它们并充分利用您支付的昂贵的Intel iCore来并行化问题....
使用split
命令生成列表。
#!/bin/bash
split -l 375000 yourfile sublist # split into lumps of 375,000 subfiles called sublist*
for f in sublist* # for all list* files
do
# Start a background process to work on one list
echo start processing file $f in background &
done
wait # till all are finished