Tôi thực sự rất ngạc nhiên vì tôi không thể tìm thấy câu trả lời cho vấn đề này ở đây, mặc dù có lẽ tôi chỉ đang sử dụng các thuật ngữ tìm kiếm sai hoặc một cái gì đó. Gần nhất tôi có thể tìm thấy là cái này , nhưng họ hỏi về việc tạo ra một phạm vi cụ thể double
với kích thước bước cụ thể và câu trả lời xử lý nó như vậy. Tôi cần một cái gì đó sẽ tạo ra các số với kích thước bắt đầu, kết thúc và bước tùy ý.
Tôi hình dung có có được một số phương pháp như thế này trong một thư viện ở đâu đó rồi, nhưng nếu vì vậy tôi đã không thể tìm thấy nó dễ dàng (một lần nữa, có lẽ tôi là chỉ sử dụng các thuật ngữ tìm kiếm sai hoặc một cái gì đó). Vì vậy, đây là những gì tôi đã tự nấu chín trong vài phút qua để làm điều này:
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);
}
}
Các phương thức này chạy một vòng lặp đơn giản nhân với step
chỉ số chuỗi và thêm vào phần start
bù. Điều này giảm thiểu các lỗi dấu phẩy động sẽ xảy ra với sự gia tăng liên tục (chẳng hạn như thêmstep
một biến vào mỗi lần lặp).
Tôi đã thêm generateSequenceRounded
phương thức cho những trường hợp kích thước bước phân đoạn có thể gây ra lỗi dấu phẩy động đáng chú ý. Nó đòi hỏi số học nhiều hơn một chút, vì vậy trong các tình huống cực kỳ nhạy cảm về hiệu năng như của chúng tôi, thật tuyệt khi có tùy chọn sử dụng phương pháp đơn giản hơn khi làm tròn là không cần thiết. Tôi nghi ngờ rằng trong hầu hết các trường hợp sử dụng chung, chi phí làm tròn sẽ không đáng kể.
Lưu ý rằng tôi cố tình loại trừ logic để xử lý các đối số "bất thường" Infinity
, như NaN
, start
> end
hoặc phủ địnhstep
kích thước cho sự đơn giản và mong muốn tập trung vào các câu hỏi trong tầm tay.
Dưới đây là một số ví dụ sử dụng và đầu ra tương ứng:
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]
Có một thư viện hiện có cung cấp loại chức năng này chưa?
Nếu không, có bất kỳ vấn đề với cách tiếp cận của tôi?
Có ai có một cách tiếp cận tốt hơn cho điều này?