Frage

I Algorithmen schreibe, die auf einer Reihe von numerischen Daten arbeiten, wo manchmal ein Wert in der Reihe null sein muss. Da jedoch diese Anwendungsleistung kritisch ist, ich habe die Verwendung von Nullable Types vermieden. Ich habe perf die Algorithmen getestet, um speziell die Leistung der Verwendung von Nullable Types vs Nicht-Nullable-Typen zu vergleichen, und im besten Fall auf NULL festlegbaren Typen sind 2x langsamer, aber oft viel schlimmer.

Der Datentyp am häufigsten verwendet wird, ist doppelt, und zur Zeit die gewählte Alternative zu null ist Double.NaN. Allerdings verstehe ich nicht die genaue beabsichtigte Verwendung für den Wert NaN ist, so bin nicht sicher, ob es irgendwelche Probleme mit diesem ich nicht vorhersehen kann und was die beste Praxis wäre.

Ich bin daran interessiert, herauszufinden, was die besten null Alternativen für die folgenden Datentypen insbesondere: Doppel- / Schwimmer, dezimal, Datum- und int / long (obwohl andere sind mehr als willkommen)

Edit: Ich glaube, ich brauche meine Anforderungen über die Leistung zu klären. Konzerte von numerischen Daten werden durch diese Algorithmen zu einer Zeit verarbeitet, die mehrere Stunden in Anspruch nimmt. Obwohl also der Unterschied zwischen zB 10 ms oder 20 ms in der Regel unerheblich ist, in diesem Szenario es wirklich tut, macht einen erheblichen Einfluss auf die Zeit genommen.

War es hilfreich?

Lösung

Nun, wenn Sie Nullable<T> ausgeschlossen haben, werden Sie mit Bereichswerten links - das heißt eine magische Zahl, die Sie als null behandeln. Während dies nicht der Fall ist ideal , ist es nicht ungewöhnlich, entweder - zum Beispiel, viele der wichtigsten Framework-Code behandelt als null die gleiche DateTime.MinValue. Das zumindest bewegt den Schaden weit weg von gemeinsamen Werten ...

Bearbeiten markieren nur dort, wo keine NaN

Also, wo es keine NaN, vielleicht .MinValue verwenden - aber nur daran erinnern, was Übel passiert, wenn Sie versehentlich verwenden , die denselben Wert die gleiche Anzahl Bedeutung ...

Offensichtlich für nicht signierte Daten Sie .MaxValue benötigen (vermeiden Null !!!).

Persönlich würde ich versuchen Nullable<T> zu verwenden, wie meine Absicht sicherer ausdrücken ... möglicherweise kann Ihren Nullable<T> Code zu optimieren, vielleicht. Und auch - durch die Zeit, die Sie haben für die magische Zahl in allen Orten, überprüft es nötig ist, vielleicht wird es nicht viel schneller als Nullable<T>

Andere Tipps

Ich bin nicht einverstanden mit etwas Gravell auf diesem speziellen Rand Fall: ein Null-ed Variable betrachtet wird ‚nicht definiert‘, es gibt keinen Wert hat. Also was auch immer verwendet wird, um zu signalisieren, das ist in Ordnung: sogar magische Zahlen, aber mit magischen Zahlen muss man berücksichtigen, dass eine magische Zahl wird verfolgen Sie immer in der Zukunft, wenn es ganz plötzlich einen ‚gültig‘ Wert wird. Mit Double.NaN Sie müssen nicht für die Angst vor: es ist nie ein gültiges Doppel werden würde. Obwohl, müssen Sie bedenken, dass NaN im Sinne der Folge von Doppel kann nur für ‚nicht definiert‘ als Marker verwendet werden, können Sie es nicht als Fehlercode in dem auch Sequenzen verwenden, offensichtlich.

So was auch immer verwendet wird, markieren ‚undefined‘: es in Zusammenhang mit der Menge von Werten klar sein muss, dass der spezifische Wert für den Wert betrachtet wird ‚undefiniert‘ und das wird auch in Zukunft nicht ändern.

Wenn Sie Nullable zu viel Mühe geben, verwenden NaN, oder was sonst auch immer, solange Sie die Konsequenzen berücksichtigen: Der gewählte Wert repräsentiert ‚undefiniert‘ und das wird bleiben.

ich an einem großen Projekt arbeite, die NaN als null Wert verwendet. Ich bin nicht ganz zufrieden mit ihm - aus ähnlichen Gründen wie bei Ihnen: nicht zu wissen, was schief gehen kann. Wir haben keine wirklichen Probleme bisher begegnet, aber bewusst sein, die folgenden:

NaN arithmetics -. Während die meiste Zeit "NaN Förderung" eine gute Sache ist, ist es vielleicht nicht immer das, was Sie erwarten,

Vergleich - Vergleich von Werten wird ziemlich teuer, wenn Sie Nans gleich vergleichen möchten. Nun, Prüfung schwimmt auf Gleichheit ohnehin nicht einfach, aber die Bestellung (a

Code-Infektion - Ich sehe eine Menge arithmetischen Code, die spezifische Behandlung von Nans erfordert richtig. So können Sie am Ende mit „Funktionen, die Nans akzeptieren“ und „Funktionen, die nicht“ aus Performance-Gründen.

Andere nicht-Endlichkeiten NaN ist nto die einzige nicht-endlichen Wert. Sollte im Auge behalten werden ...

Floating Point Ausnahmen ist kein Problem, wenn deaktiviert. Bis jemand ermöglicht es ihnen. Eine wahre Geschichte: Statische Initialisierung eines NaN in einem ActiveX-Steuerelement. Nicht beängstigend klingen, bis Sie die Installation ändern InnoSetup zu verwenden, die verwendet eine Pascal / Delphi (?) Kern, der standardmäßig aktiviert FPU Ausnahmen hat. Dauerte eine Weile, um herauszufinden.

Also, alles in allem, nichts Ernst, obwohl ich würde es vorziehen, nicht NaNs, die oft zu haben zu prüfen.


würde ich Nullable-Typen so oft wie möglich verwenden, es sei denn, sie (erwiesen) Leistung / Ressource Einschränkungen werden. Ein Fall könnte große Vektoren / Matrizen mit gelegentlichen NaNs oder große Mengen von Namen einzelner Werte , wo die Standard NaN Verhalten korrekt ist .


Alternativ können Sie einen Indexvektor für Vektoren und Matrizen, Standard „Sparse Matrix“ Implementierungen oder einen separaten Bool / Bit-Vektor verwendet werden.

Partielle Antwort:

Float und Double liefern NaN (Not a Number). NaN ist ein wenig schwierig, da pro spec, NaN! = NaN. Wenn Sie wissen wollen, ob eine Zahl NaN ist, müssen Sie Double.IsNaN () verwenden.

Siehe auch Binary Floating-Point-und .NET .

Vielleicht ist die signifikante Leistungsabnahme passiert, wenn einer von Nullable-Mitglieder oder Eigenschaften (Boxen) aufrufen.

Versuchen Sie, eine Struktur mit Doppel + boolean verwenden zu sagen, ob der angegebene Wert ist oder nicht.

Man kann mit Nullable<T> assoziiert einige der Leistungsabfall vermeiden, indem Sie Ihre eigene Struktur zu definieren

struct MaybeValid<T>
{
    public bool isValue;
    public T Value;
}

Falls gewünscht, kann man definieren Konstruktor, oder einen Umwandlungsoperator von T MaybeValid<T> usw. aber übermäßigem Gebrauch von solchen Dingen ergeben kann suboptimale Leistung. Exposed-Feld structs kann effizient sein, wenn man nicht mehr benötigten Daten Kopieren vermeidet. Manche Menschen Stirnrunzeln kann auf der Vorstellung von exponierten Bereichen, aber sie können die Eigenschaften massiv effizienter sein. Wenn eine Funktion, die ein T zurückkehren müsse eine Variable vom Typ T haben, um den Rückgabewert zu halten, eine MaybeValid<Foo> mit einfach erhöht um 4 die Größe der Sache zurückgeschickt werden. Im Gegensatz dazu würde eine Nullable<Foo> mit, dass die Funktion zuerst die Foo berechnet und dann eine Kopie davon an den Konstruktor für die Nullable<Foo> passieren. eine Nullable<Foo> Rückkehr wird ferner verlangen, dass jeder Code, der den zurückgegebenen Wert verwenden will, muss mindestens eine zusätzliche Kopie an einen Lagerort (Variable oder temporäre) vom Typ Foo machen, bevor es etwas Sinnvolles damit machen kann. Im Gegensatz dazu kann Code das Value Feld einer Variable vom Typ Foo etwa so effizient wie jede andere Variable verwenden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top