给定任意双下限,双上限和双增量,最快方式确定给定输入加倍的范围是什么?如果你不关心内存使用,使用预先计算或其他一些方法,你能比使用双重划分的显而易见的方法做得更好吗?注意:重复使用此类不太可能具有完全相同的double值,换句话说,将结果缓存在Map<Double, Double>
中可能无济于事。
public class RangeFinder {
private double lowerBound;
private double higherBound;
private double increment;
public RangeFinder(double lowerBound, double higherBound, double increment) {
if(increment < 0) throw new IllegalArgumentException("Increment cannot be negative!");
this.lowerBound = lowerBound;
this.higherBound = higherBound;
this.increment = increment;
}
public int getRange(double number) {
if (number < lowerBound) return 0;
if (number > higherBound) number = higherBound;
return (int) Math.round((number - lowerBound) / increment);
}
public static void main(String... args) {
double lower = 2.3d;
double higher = 3.9;
double inc = 0.1d;
double[] inputs = { 0.5d, 2.25, 2.35, 2.4, 3.0, 3.8, 3.85, 3.9, 4.0 };
RangeFinder rf = new RangeFinder(lower, higher, inc);
System.out.format("Lower bound: %1.2f%n", lower);
System.out.format("Upper bound: %1.2f%n", higher);
System.out.format("Increment: %1.2f%n", inc);
for(double inp : inputs) {
System.out.format("Input: %1.2f\tOutput: %d%n",
inp, rf.getRange(inp));
}
}
}
Lower bound: 2.30
Upper bound: 3.90
Increment: 0.10
Input: 0.50 Output: 0
Input: 2.25 Output: 0
Input: 2.35 Output: 1
Input: 2.40 Output: 1
Input: 3.00 Output: 7
Input: 3.80 Output: 15
Input: 3.85 Output: 16
Input: 3.90 Output: 16
Input: 4.00 Output: 16
答案 0 :(得分:1)
替换行:
return (int) Math.round((number - lowerBound) / increment);
用这个:
return (int) ((number - lowerBound + 1e-7) / increment);
它提供了更明智的结果,并且在我的临时基准测试中运行速度提高了约30倍(因为它不再调用圆形)。
将1e-7“epsilon”声明为常量,并将其值调整为所需的误差范围是个好主意。搜索浮点舍入误差(或类似内容)以查找有关该主题的更多信息,例如this article。