将 BigDecimals 列表与特定值和 return 最接近的值进行比较
Compare BigDecimals List to a specific value and return closest value
我有一个大十进制值列表,还有一个特定输入也是一个 BigDecimal。我想将特定输入与列表中的值和 select 最接近特定输入的值进行比较。请问有什么建议吗?
private static BigDecimal getWageMultiplier(List<BigDecimal> values, BigDecimal valueAmount) {
values.sort(BigDecimal::compareTo);
int index = values.indexOf(valueAmount);
// Check for an exact match and if not get the index of the previous value
if (index == -1) {
// start with the highest index, in case there is no higher value than the previous
index = values.size() - 1;
for (int i = 0; i < values.size(); i++) {
//work out the value from the List<BigDecimal> values that is closest to BigDecimal valueAmount
}
}
int finalIndex = (index);
return finalIndex != -1 ? values.get(finalIndex) : BigDecimal.ZERO;
}
您可以通过比较列表中每个值与给定值之间的绝对差异来实现此目的:
public static BigDecimal findClosest(List<BigDecimal> list, BigDecimal value) {
return list.stream()
.min(Comparator.comparing(a -> value.subtract(a).abs()))
.orElseThrow(() -> new IllegalArgumentException("Empty collection"));
}
我们可以通过遍历列表并使用 BigDecimal 函数(如减法和 abs(绝对值))来完成此操作。以下解决方案采用 O(N)。
注意:这个解法不是用java8.当然我们可以用Java8.
来解
private static BigDecimal getWageMultiplier(List<BigDecimal> values, BigDecimal valueAmount) {
BigDecimal minDifference = values.get(0).subtract(valueAmount).abs();
int index = 0;
for(int i = 1; i < values.size(); i++) {
BigDecimal difference = values.get(i).subtract(valueAmount).abs();
if(difference.compareTo(minDifference) < 0) {
minDifference = difference;
index = i;
}
}
return values.get(index);
}
这是一个针对长列表的快速解决方案,将大小分成两半:
int getMinDist (List<Integer> values, int target) {
if (values.size () == 1) return values.get (0);
int mid = values.size ()/ 2;
int left= Math.max (0, mid -1);
int v0 = values.get (left);
int v1 = values.get (mid);
// println (left + " " + mid + " | " + v0 + " " + v1);
int av0 = Math.abs (target - v0);
int av1 = Math.abs (v1 - target);
return (av0 <= av1) ? getMinDist (values.subList (0, left+1), target) : getMinDist (values.subList (mid, values.size ()), target);
}
List<Integer> vals = Arrays.asList (1, 3, 5, 9, 17, 18, 19)
-> getMinDist (vals, 16)
2 3 | 5 9
1 2 | 17 18
0 1 | 9 17
| Expression value is: 17
| assigned to temporary variable of type int
-> getMinDist (vals, 4)
2 3 | 5 9
0 1 | 1 3
0 1 | 3 5
| Expression value is: 3
| assigned to temporary variable of type int
将 int 替换为 BigDecimal,您的案例留作练习。
与其拆分 List,不如传递下、上索引,从 0 和 list.size()-1 开始,甚至可能更好。
我有一个大十进制值列表,还有一个特定输入也是一个 BigDecimal。我想将特定输入与列表中的值和 select 最接近特定输入的值进行比较。请问有什么建议吗?
private static BigDecimal getWageMultiplier(List<BigDecimal> values, BigDecimal valueAmount) {
values.sort(BigDecimal::compareTo);
int index = values.indexOf(valueAmount);
// Check for an exact match and if not get the index of the previous value
if (index == -1) {
// start with the highest index, in case there is no higher value than the previous
index = values.size() - 1;
for (int i = 0; i < values.size(); i++) {
//work out the value from the List<BigDecimal> values that is closest to BigDecimal valueAmount
}
}
int finalIndex = (index);
return finalIndex != -1 ? values.get(finalIndex) : BigDecimal.ZERO;
}
您可以通过比较列表中每个值与给定值之间的绝对差异来实现此目的:
public static BigDecimal findClosest(List<BigDecimal> list, BigDecimal value) {
return list.stream()
.min(Comparator.comparing(a -> value.subtract(a).abs()))
.orElseThrow(() -> new IllegalArgumentException("Empty collection"));
}
我们可以通过遍历列表并使用 BigDecimal 函数(如减法和 abs(绝对值))来完成此操作。以下解决方案采用 O(N)。 注意:这个解法不是用java8.当然我们可以用Java8.
来解private static BigDecimal getWageMultiplier(List<BigDecimal> values, BigDecimal valueAmount) {
BigDecimal minDifference = values.get(0).subtract(valueAmount).abs();
int index = 0;
for(int i = 1; i < values.size(); i++) {
BigDecimal difference = values.get(i).subtract(valueAmount).abs();
if(difference.compareTo(minDifference) < 0) {
minDifference = difference;
index = i;
}
}
return values.get(index);
}
这是一个针对长列表的快速解决方案,将大小分成两半:
int getMinDist (List<Integer> values, int target) {
if (values.size () == 1) return values.get (0);
int mid = values.size ()/ 2;
int left= Math.max (0, mid -1);
int v0 = values.get (left);
int v1 = values.get (mid);
// println (left + " " + mid + " | " + v0 + " " + v1);
int av0 = Math.abs (target - v0);
int av1 = Math.abs (v1 - target);
return (av0 <= av1) ? getMinDist (values.subList (0, left+1), target) : getMinDist (values.subList (mid, values.size ()), target);
}
List<Integer> vals = Arrays.asList (1, 3, 5, 9, 17, 18, 19)
-> getMinDist (vals, 16)
2 3 | 5 9
1 2 | 17 18
0 1 | 9 17
| Expression value is: 17
| assigned to temporary variable of type int
-> getMinDist (vals, 4)
2 3 | 5 9
0 1 | 1 3
0 1 | 3 5
| Expression value is: 3
| assigned to temporary variable of type int
将 int 替换为 BigDecimal,您的案例留作练习。
与其拆分 List,不如传递下、上索引,从 0 和 list.size()-1 开始,甚至可能更好。