Aslında burada bunun cevabını bulamadığım için çok şaşırdım, ama belki de sadece yanlış arama terimlerini falan kullanıyorum. Bulabildiğim en yakın şey bu , ama double
belirli bir adım büyüklüğüne sahip belirli bir s aralığı üretmeyi soruyorlar ve cevaplar böyle davranıyor. Ben rasgele başlangıç, bitiş ve adım boyutu ile sayıları üretecek bir şeye ihtiyacım var.
Orada anlamaya sahip bir yerde zaten bir kütüphane bu gibi bazı yöntem olmak, ama kolayca bulmak mümkün değildi eğer öyleyse (yine, belki de yanlış arama terimlerini falan kullanıyorum). İşte bunu yapmak için son birkaç dakika içinde kendi başıma pişirdim:
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);
}
}
Bu yöntemler step
, dizi dizini ile çarpılan ve start
ofsete eklenen basit bir döngü çalıştırır . Bu, sürekli artışla ( step
her bir yinelemede bir değişkene ekleme yapmak gibi) meydana gelebilecek birleşik kayan nokta hatalarını azaltır.
generateSequenceRounded
Bir kesirli adım büyüklüğünün belirgin kayan nokta hatalarına neden olabileceği durumlar için yöntemi ekledim . Biraz daha aritmetik gerektirir, bu nedenle bizimki gibi son derece performansa duyarlı durumlarda, yuvarlama gereksiz olduğunda daha basit yöntemi kullanma seçeneğine sahip olmak güzeldir. Çoğu genel kullanım durumunda yuvarlama yükünün ihmal edilebilir olacağını düşünüyorum.
Ben kasıtlı gibi "anormal" argümanları işlemek için mantığı hariç geldiğini hatırlatırız Infinity
, NaN
, start
> end
, negatif veya step
basitlik için boyut ve eldeki soru üzerine odaklanmak istiyoruz.
Aşağıda bazı örnek kullanım ve karşılık gelen çıktılar verilmiştir:
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]
Bu tür bir işlevsellik sağlayan mevcut bir kütüphane var mı?
Değilse, yaklaşımımla ilgili herhangi bir sorun var mı?
Herkes bu konuda daha iyi bir yaklaşım var mı?