生成 List<Double>给定开始、结束和步骤的值序列的最佳方法?
我真的很惊讶我无法在这里找到这个问题的答案,尽管也许我只是使用了错误的搜索词或其他东西。我能找到的最接近的是这个,但他们询问如何生成具有特定步长的特定范围的s,答案就是这样对待的。我需要一些东西来生成具有任意开始,结束和步长大小的数字。double
我认为在某个地方的图书馆里一定有这样的方法,但如果是这样,我无法轻松找到它(再次,也许我只是使用了错误的搜索词或其他东西)。因此,以下是我在过去几分钟内自己烹饪的内容:
import java.lang.Math;
import java.util.List;
import java.util.ArrayList;
public class DoubleSequenceGenerator {
/**
* Generates a List of Double values beginning with `start` and ending with
* the last step from `start` which includes the provided `end` value.
**/
public static List<Double> generateSequence(double start, double end, double step) {
Double numValues = (end-start)/step + 1.0;
List<Double> sequence = new ArrayList<Double>(numValues.intValue());
sequence.add(start);
for (int i=1; i < numValues; i++) {
sequence.add(start + step*i);
}
return sequence;
}
/**
* Generates a List of Double values beginning with `start` and ending with
* the last step from `start` which includes the provided `end` value.
*
* Each number in the sequence is rounded to the precision of the `step`
* value. For instance, if step=0.025, values will round to the nearest
* thousandth value (0.001).
**/
public static List<Double> generateSequenceRounded(double start, double end, double step) {
if (step != Math.floor(step)) {
Double numValues = (end-start)/step + 1.0;
List<Double> sequence = new ArrayList<Double>(numValues.intValue());
double fraction = step - Math.floor(step);
double mult = 10;
while (mult*fraction < 1.0) {
mult *= 10;
}
sequence.add(start);
for (int i=1; i < numValues; i++) {
sequence.add(Math.round(mult*(start + step*i))/mult);
}
return sequence;
}
return generateSequence(start, end, step);
}
}
这些方法运行一个简单的循环,将 乘以序列索引并添加到偏移量。这减轻了连续递增时发生的复合浮点错误(例如在每次迭代时将 添加到变量中)。step
start
step
我为那些小数步长可能导致明显浮点错误的情况添加了该方法。它确实需要更多的算术,因此在像我们这样对性能极其敏感的情况下,当不需要舍入时,可以选择使用更简单的方法。我怀疑在大多数一般用例中,舍入开销可以忽略不计。generateSequenceRounded
请注意,我故意排除了处理“异常”参数的逻辑,例如 、、> 或负大小,以简化并希望专注于手头的问题。Infinity
NaN
start
end
step
以下是一些示例用法和相应的输出:
System.out.println(DoubleSequenceGenerator.generateSequence(0.0, 2.0, 0.2))
System.out.println(DoubleSequenceGenerator.generateSequenceRounded(0.0, 2.0, 0.2));
System.out.println(DoubleSequenceGenerator.generateSequence(0.0, 102.0, 10.2));
System.out.println(DoubleSequenceGenerator.generateSequenceRounded(0.0, 102.0, 10.2));
[0.0, 0.2, 0.4, 0.6000000000000001, 0.8, 1.0, 1.2000000000000002, 1.4000000000000001, 1.6, 1.8, 2.0]
[0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0]
[0.0, 10.2, 20.4, 30.599999999999998, 40.8, 51.0, 61.199999999999996, 71.39999999999999, 81.6, 91.8, 102.0]
[0.0, 10.2, 20.4, 30.6, 40.8, 51.0, 61.2, 71.4, 81.6, 91.8, 102.0]
是否有现有的库已经提供了这种功能?
如果没有,我的方法有问题吗?
有没有人有更好的方法?