对双大十进制数进行排序的更好方法
Better way to sort double Big Decimal numbers
我有字符串列表,想要对值进行排序。
List<String> list = new ArrayList<String>();
list.add("200.1043725170");
list.add("100.1043725171");
list.add("100.1043725170");
list.add("65535.4294967295");
list.add("4294967295.65535");
尝试了几种方法来对相同的对象进行排序,但未能通过有效的解决方案来获得准确的结果。
list.forEach(value ->{
dList.add(BigDecimal.valueOf(Double.parseDouble(value)));
});
Collections.sort(dList);
使用上述方法,值正在排序,但最后一个零不会在 (.) 之后打印,因为它不被认为是相关的。但我也需要尾部零,因为我们正在其他地方比较这些值。
我正在寻找的最终输出是
100.1043725170
100.1043725171
200.1043725170
65535.4294967295
4294967295.65535
这里有任何用有效方法实现相同目标的建议
更新
最好的解决方案是在 中,非常简短的一行代码。以下是我的两种方法。不那么简洁,但我会把它们留在这里,因为它们可能会让读者感兴趣。
避免double
/Double
您的代码将您的字符串转换为 double
或 Double
值。这样做会引入固有的 inaccuracy of floating-point 技术。如果您关心准确性,请避免这样做。
相反,将您的输入字符串直接解析为 BigDecimal
个对象。
转换为BigDecimal
后重新生成字符串
您必须将字符串直接解析为 BigDecimal
。将这些对象收集到列表中。种类。然后通过为每个 BigDecimal
生成一个新的字符串值来生成一个新的 String
对象列表。 Stack Overflow 上已经多次介绍了这些步骤中的每一个。搜索以了解更多信息。
NavigableMap< BigDecimal , String >
或者,使用 SortedMap
/NavigableMap
。将从每个输入字符串派生的 BigDecimal
映射到该字符串。这些键是 BigDecimal
个对象(Comparable
个对象),它们会按数学顺序自动排序。将调用 values
产生的集合提供给新的 List
的构造函数以获得结果。
List < String > list = List.of( "200.1043725170" , "100.1043725171" , "100.1043725170" , "65535.4294967295" , "4294967295.65535" );
NavigableMap < BigDecimal, String > map =
list
.stream()
.collect(
Collectors.toMap(
( String s ) -> new BigDecimal( s ) ,
Function.identity() ,
( existing , replacement ) -> existing , // In case of duplicate key conflict, first one wins.
TreeMap :: new
)
);
List < String > result = List.copyOf( map.values() );
System.out.println( result );
看到这个code run live at IdeOne.com。
[100.1043725170, 100.1043725171, 200.1043725170, 65535.4294967295, 4294967295.65535]
您可以将列表保留为按从每个字符串元素生成的 BigDecimal 排序的字符串列表:
list.sort(Comparator.comparing(BigDecimal::new));
看到这个code run live at IdeOne.com。
[100.1043725170, 100.1043725171, 200.1043725170, 65535.4294967295, 4294967295.65535]
我有字符串列表,想要对值进行排序。
List<String> list = new ArrayList<String>();
list.add("200.1043725170");
list.add("100.1043725171");
list.add("100.1043725170");
list.add("65535.4294967295");
list.add("4294967295.65535");
尝试了几种方法来对相同的对象进行排序,但未能通过有效的解决方案来获得准确的结果。
list.forEach(value ->{
dList.add(BigDecimal.valueOf(Double.parseDouble(value)));
});
Collections.sort(dList);
使用上述方法,值正在排序,但最后一个零不会在 (.) 之后打印,因为它不被认为是相关的。但我也需要尾部零,因为我们正在其他地方比较这些值。
我正在寻找的最终输出是
100.1043725170
100.1043725171
200.1043725170
65535.4294967295
4294967295.65535
这里有任何用有效方法实现相同目标的建议
更新
最好的解决方案是在
避免double
/Double
您的代码将您的字符串转换为 double
或 Double
值。这样做会引入固有的 inaccuracy of floating-point 技术。如果您关心准确性,请避免这样做。
相反,将您的输入字符串直接解析为 BigDecimal
个对象。
转换为BigDecimal
后重新生成字符串
您必须将字符串直接解析为 BigDecimal
。将这些对象收集到列表中。种类。然后通过为每个 BigDecimal
生成一个新的字符串值来生成一个新的 String
对象列表。 Stack Overflow 上已经多次介绍了这些步骤中的每一个。搜索以了解更多信息。
NavigableMap< BigDecimal , String >
或者,使用 SortedMap
/NavigableMap
。将从每个输入字符串派生的 BigDecimal
映射到该字符串。这些键是 BigDecimal
个对象(Comparable
个对象),它们会按数学顺序自动排序。将调用 values
产生的集合提供给新的 List
的构造函数以获得结果。
List < String > list = List.of( "200.1043725170" , "100.1043725171" , "100.1043725170" , "65535.4294967295" , "4294967295.65535" );
NavigableMap < BigDecimal, String > map =
list
.stream()
.collect(
Collectors.toMap(
( String s ) -> new BigDecimal( s ) ,
Function.identity() ,
( existing , replacement ) -> existing , // In case of duplicate key conflict, first one wins.
TreeMap :: new
)
);
List < String > result = List.copyOf( map.values() );
System.out.println( result );
看到这个code run live at IdeOne.com。
[100.1043725170, 100.1043725171, 200.1043725170, 65535.4294967295, 4294967295.65535]
您可以将列表保留为按从每个字符串元素生成的 BigDecimal 排序的字符串列表:
list.sort(Comparator.comparing(BigDecimal::new));
看到这个code run live at IdeOne.com。
[100.1043725170, 100.1043725171, 200.1043725170, 65535.4294967295, 4294967295.65535]