Saya sebenarnya sangat terkejut saya tidak dapat menemukan jawaban untuk ini di sini, meskipun mungkin saya hanya menggunakan istilah pencarian yang salah atau sesuatu. Yang paling dekat yang bisa saya temukan adalah ini , tetapi mereka bertanya tentang menghasilkan kisaran double
s tertentu dengan ukuran langkah spesifik, dan jawaban memperlakukannya seperti itu. Saya membutuhkan sesuatu yang akan menghasilkan angka dengan ukuran awal, akhir dan langkah yang sewenang-wenang.
Saya pikir ada memiliki menjadi beberapa metode seperti ini di perpustakaan di suatu tempat sudah, tapi kalau jadi saya tidak dapat menemukannya dengan mudah (sekali lagi, mungkin aku hanya menggunakan istilah pencarian yang salah atau sesuatu). Jadi inilah yang saya lakukan sendiri dalam beberapa menit terakhir untuk melakukan ini:
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);
}
}
Metode-metode ini menjalankan loop sederhana mengalikan step
dengan indeks urutan dan menambahkan ke start
offset. Ini mengurangi kesalahan floating-point majemuk yang akan terjadi dengan peningkatan berkelanjutan (seperti menambahkan step
variabel ke setiap iterasi).
Saya menambahkan generateSequenceRounded
metode untuk kasus-kasus di mana ukuran langkah fraksional dapat menyebabkan kesalahan floating-point. Memang diperlukan aritmatika sedikit lebih, sehingga dalam situasi yang sangat sensitif seperti kita, bagus untuk memiliki pilihan menggunakan metode yang lebih sederhana ketika pembulatan tidak diperlukan. Saya menduga bahwa dalam sebagian besar kasus penggunaan umum, overhead pembulatan akan diabaikan.
Perhatikan bahwa saya sengaja dikeluarkan logika untuk menangani "abnormal" argumen seperti Infinity
, NaN
, start
> end
, atau negatif step
ukuran untuk kesederhanaan dan ingin fokus pada pertanyaan di tangan.
Berikut beberapa contoh penggunaan dan output yang sesuai:
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]
Apakah sudah ada perpustakaan yang menyediakan fungsionalitas semacam ini?
Jika tidak, apakah ada masalah dengan pendekatan saya?
Apakah ada yang punya pendekatan yang lebih baik untuk ini?