Ich bin eigentlich sehr überrascht, dass ich hier keine Antwort darauf finden konnte, obwohl ich vielleicht nur die falschen Suchbegriffe verwende oder so. Closest ich finden konnte , ist dies , aber sie fragen über einen bestimmten Bereich der Erzeugung von double
s mit einem bestimmten Schrittgröße, und die Antworten behandeln sie als solche. Ich brauche etwas, das die Zahlen mit beliebiger Start-, End- und Schrittgröße generiert.
Ich denke, irgendwo in einer Bibliothek muss es schon eine solche Methode geben, aber wenn ja, konnte ich sie nicht leicht finden (wieder verwende ich vielleicht nur die falschen Suchbegriffe oder so). Folgendes habe ich mir in den letzten Minuten selbst ausgedacht:
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);
}
}
Diese Methoden führen eine einfache Schleife aus, die das step
mit dem Sequenzindex multipliziert und zum start
Offset addiert . Dies verringert das Zusammensetzen von Gleitkommafehlern, die bei kontinuierlicher Inkrementierung auftreten würden (z. B. Hinzufügen der step
Variablen zu einer Variablen bei jeder Iteration).
Ich habe die generateSequenceRounded
Methode für Fälle hinzugefügt , in denen eine gebrochene Schrittgröße zu merklichen Gleitkommafehlern führen kann. Es erfordert etwas mehr Arithmetik, daher ist es in extrem leistungsempfindlichen Situationen wie unserer schön, die Option zu haben, die einfachere Methode zu verwenden, wenn die Rundung nicht erforderlich ist. Ich vermute, dass in den meisten allgemeinen Anwendungsfällen der Rundungsaufwand vernachlässigbar wäre.
Beachten Sie, dass ich ausgeschlossen Logik absichtlich für „abnormal“ Argumente wie Handhabung Infinity
, NaN
, start
> end
, oder eine negative step
Größe für Einfachheit und begehrt auf der Frage auf der Hand zu konzentrieren.
Hier einige Beispiele für die Verwendung und die entsprechende Ausgabe:
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]
Gibt es bereits eine Bibliothek, die diese Art von Funktionalität bietet?
Wenn nicht, gibt es Probleme mit meinem Ansatz?
Hat jemand einen besseren Ansatz dafür?