Domanda

Sto scrivendo algoritmi che lavorano su una serie di dati numerici, in cui a volte, un valore in serie deve essere null.Tuttavia, perché questa applicazione è prestazioni critiche, ho evitato l'uso di tipi nullable.Ho perf testato gli algoritmi appositamente per confrontare le prestazioni di utilizzo di tipi nullable vs non-tipi nullable, e nel migliore dei casi questi tipi sono 2x più lento, ma spesso di gran lunga peggiore.

Il tipo di dati utilizzati più spesso è il doppio, e attualmente l'alternativa scelta null è il doppio.NaN.Tuttavia capisco che questa non è l'esatta destinazione d'uso per il valore NaN, così sono sicuro se ci sono eventuali problemi con questo non posso prevedere e ciò che la migliore pratica vorresti essere.

Sono interessato a scoprire quello che i migliori null alternative per i seguenti tipi di dati, in particolare:camera matrimoniale/float, decimale, DateTime, int/long (anche se gli altri sono più che benvenuti)

Edit:Penso che ho bisogno di chiarire i miei requisiti sulle prestazioni.Giga di dati numerici sono trattati attraverso questi algoritmi in un momento che richiede diverse ore.Pertanto, anche se la differenza tra ad esempio 10ms o 20ms è di solito insignificante, in questo scenario davvero non rende un impatto significativo per il tempo impiegato.

È stato utile?

Soluzione

Bene, se hai escluso Nullable<T>, si sono lasciati con valori di dominio - vale a dire un numero magico che ti trattano come nullo. Anche se questo non è ideale , non è raro che sia - per esempio, molte delle principali tratta di codice quadro DateTime.MinValue lo stesso di nulla. Questo almeno si muove il danno lontano da valori comuni ...

modifica per evidenziare solo in assenza di NaN

Allora, dove non c'è NaN, magari utilizzare .MinValue - ma solo ricordare che cosa mali accadere se accidentalmente usare che lo stesso valore che significa lo stesso numero ...

Ovviamente per i dati senza segno avrete bisogno .MaxValue (evitare lo zero !!!).

Personalmente, mi piacerebbe provare a utilizzare Nullable<T> come esprimere il mio intento in modo più sicuro ... ci possono essere modi per ottimizzare il codice Nullable<T>, forse. E anche -? Per il momento aver controllato per il numero magico in tutti i posti è necessario, forse non sarà molto più veloce di Nullable<T>

Altri suggerimenti

I po 'in disaccordo con Gravell su questo specifico caso limite: una variabile Null-ed è considerato 'non definito', non ha un valore. Quindi, tutto ciò che è utilizzato per segnalare che è OK: anche i numeri magici, ma con numeri magici si deve tener conto che un numero magico sempre perseguiterà in futuro, quando si trasforma in un valore 'valida' tutto ad un tratto. Con Double.NaN non devi avere paura per questo: non è mai sta per diventare un letto valido. Anche se, si deve considerare che NaN nel senso della sequenza dei doppi può essere utilizzato solo come marker per 'non definito', non è possibile utilizzare come un codice di errore nelle sequenze pure, ovviamente.

Quindi, tutto ciò che è utilizzato per contrassegnare 'undefined': deve essere chiaro nel contesto della serie di valori che quel valore specifico è considerato il valore per 'undefined' e che non cambierà in futuro.

Se Nullable darvi troppi problemi, utilizzare NaN, o qualsiasi altra cosa, a patto che si considerano le conseguenze: il valore selezionato rappresenta 'undefined' e che rimarrà.

Sto lavorando su un progetto di grandi dimensioni che utilizza NaN come un null valore.Io non sono del tutto a proprio agio con esso - per ragioni simili a quelle del tuo:non sapendo che cosa può andare storto.Non abbiamo incontrato alcun problema reale, ma essere consapevoli delle seguenti operazioni:

NaN aritmetica Mentre la maggior parte del tempo, "NaN promozione" è una buona cosa, potrebbe non essere sempre quello che ti aspetti.

Confronto - Confronto dei valori diventa piuttosto costoso, se si desidera che NaN è uguali.Ora, il test di carri allegorici per la parità non è semplice comunque, ma di ordinazione (un < b) si possono ottenere veramente brutto, perchè nan a volte è necessario essere più piccoli, a volte più grandi rispetto a valori normali.

Codice Infezione - Vedo un sacco di aritmetica codice che richiede un trattamento specifico di NaN essere corretto.Così si finisce con "le funzioni che accettano NaN" e "funzioni" non per motivi di prestazioni.

Altri non finites NaN è nper l'unico non-finito di valore.Dovrebbe essere tenuto in mente...

In Virgola Mobile Eccezioni non sono un problema quando è disabilitato.Fino a quando qualcuno si permette loro di.Storia vera:Statico intialization di un NaN in un controllo ActiveX.Non suono spaventoso, finché non si cambia, installazione, utilizzo InnoSetup, che utilizza un Pascal/Delphi(?) core, che ha FPU eccezioni abilitata per impostazione predefinita.Mi ha preso un po ' per capire.

Quindi, tutto sommato, niente di grave, anche se preferisco non considerare NaNs che spesso.


Mi piacerebbe utilizzare tipi Nullable il più spesso possibile, a meno che non sono (risultato) prestazioni / ressource vincoli.Un caso potrebbe essere di grandi vettori / matrici, con occasionale NaNs, o grandi insiemi di valori individuali in cui il valore predefinito NaN comportamento è corretto.


In alternativa, è possibile utilizzare un indice vettore di vettori e matrici standard "matrice sparsa" implementazioni, o un bool/vettore di bit.

parziale risposta:

float e double forniscono NaN (Not a Number). Nan è un po 'difficile in quanto, per spec, NaN! = NaN. Se vuoi sapere se un numero è NaN, è necessario utilizzare Double.IsNaN ().

Si veda anche binario in virgola mobile e .NET .

Forse il calo significativo delle prestazioni avviene quando chiamando uno dei membri o le proprietà di Nullable (boxe).

Prova ad utilizzare una struttura con il doppio + un valore booleano che indica se il valore è specificato o meno.

Si può evitare alcuni dei degrado delle prestazioni associato con Nullable<T> definendo la propria struttura

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

Se lo si desidera, si può definire il costruttore, o un operatore di conversione da T a MaybeValid<T>, ecc ma uso eccessivo di queste cose può produrre risultati non ottimali. struct-campo esposta può essere efficiente se si evita la copia di dati non necessari. Alcune persone possono disapprovano l'idea dei campi di vista, ma possono essere in maniera massiccia più efficiente che le proprietà. Se una funzione che restituisce un T avrebbe bisogno di avere una variabile di tipo T tenere suo valore di ritorno, utilizzando un MaybeValid<Foo> semplicemente aumenta di 4 il formato della cosa da restituire. Al contrario, utilizzando un Nullable<Foo> richiederebbe che la funzione prima calcolare il Foo e poi passare una copia al costruttore per il Nullable<Foo>. Inoltre, restituendo un Nullable<Foo> richiederà che qualsiasi codice che vuole utilizzare il valore restituito deve fare almeno una copia in più per una posizione di archiviazione (variabile o temporanea) di tipo Foo prima che possa fare qualcosa di utile con esso. Al contrario, il codice può utilizzare il campo Value di una variabile di tipo Foo circa la stessa efficienza come qualsiasi altra variabile.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top