Сортировать массив примитивных значений (double[]
, int[]
, long[]
и т.п.) можно только в "естественном" порядке. Для необычной сортировки как в данном случае по длине дробной части потребуется либо использовать массив соответствующих классов-обёрток, т.е. Double[]
, к которому можно применить метод Arrays::sort(T[] a, Comparator<? super T> comp)
, либо преобразовать с помощью Stream API.
(Обновление) Для корректной сортировки нужно обеспечить ненулевое значение в старшем разряде (спасибо @Stanislav Volodarskiy).
Также потребуется обеспечить корректное форматирование некоторых чисел (спасибо @siarhei987), поскольку они могут быть по умолчанию преобразованы в строку с "научной" записью с указанием экспоненты.
Так как double
может хранить до 17 значащих цифр, потребуется отформатировать каждое число, убрав нули в конце. При форматировании следует принять во внимание локаль, чтобы корректно обрабатывался десятичный разделитель
Double[] arr = {
1.234, 1.2, 22d, 1.001, 23.41, 10.00456, 3.1415, Math.PI
};
Arrays.sort(arr, Comparator.comparingLong(x -> {
String s = String.format(Locale.US, "%.17f", x).replaceAll("0+$", "");
return Long.parseLong(1 + s.substring(s.indexOf(".") + 1));
}));
System.out.println(Arrays.toString(arr));
// -> [22.0, 1.2, 23.41, 1.001, 1.234, 3.1415, 10.00456, 3.141592653589793]
Аналогично:
double[] arr = {
1.234, 1.2, 22, 1.001, 23.41, 10.00456, 3.1415, 11.21, Math.PI,
10.234, 1238.41,
12345678.02, // 10 знаков 8+2
12345678901234.5678, // 18 знаков 14+4
1234567890999.56789, // 18 знаков 13+5
-.123456789012345678, // 18 знаков 0+18
-12.3456789012345678, // 18 знаков 2+16
987654321012345678.91 // 20 знаков 18+2
};
arr = Arrays.stream(arr)
.boxed()
.sorted(Comparator.comparingLong(
x -> Long.parseLong(1 + String.format(Locale.US, "%.17f", x)
.replaceAll("0+$", "") // удалить 0 в конце
.replaceAll("^.*\\.", "") // удалить всё до точки в начале
)
))
.mapToDouble(x -> x)
.toArray();
for (double d : arr) {
System.out.println(String.format(Locale.US, "%.17f", d).replaceAll("\\.?0+$", ""));
}
Некоторые числа будут округлены, так как у типа double
не хватает точности
22
987654321012345730
1.2
12345678.02
11.21
23.41
1238.41
1.001
1.234
10.234
12345678901234.568
3.1415
1234567890999.5679
10.00456
3.141592653589793
-12.345678901234567
-0.12345678901234568