2013-03-08 5 views
8

Il mio programma salva un pointcloud in un file, dove ogni pointcloud è uno Point3D[,], dallo spazio dei nomi System.Windows.Media.Media3D. Questo dimostra una riga del file di output (in portoghese):Come modificare la rappresentazione della stringa NaN in C#?

-112,644088741971;71,796623005014;NaN (Não é um número) 

mentre mi piacerebbe che fosse (in modo da essere correttamente analizzato in seguito):

-112,644088741971;71,796623005014;NaN 

Il blocco di codice che genera il file è qui:

var lines = new List<string>(); 

for (int rows = 0; rows < malha.GetLength(0); rows++) { 
    for (int cols = 0; cols < malha.GetLength(1); cols++) { 

     double x = coordenadas_x[cols]; 
     double y = coordenadas_y[rows]; 
     double z; 

     if (SomeTest()) { 
      z = alglib.rbfcalc2(model, x, y); 
     } else { 
      z = double.NaN; 
     } 

     var p = new Point3D(x, y, z); 
     lines.Add(p.ToString());      

     malha[rows, cols] = p; 
    } 
} 

File.WriteAllLines("../../../../dummydata/malha.txt", lines); 

sembra che il metodo double.NaN.ToString(), chiamato dall'interno Point3D.ToString(), include quella racchiusa tra parentesi "spiegazione aggiuntiva", che io non voglio affatto.

C'è un modo per modificare/sovrascrivere questo metodo in modo che emetta solo NaN, senza la parentesi parte?

+2

Dai un'occhiata a NumberFormatInfo.NaNSymbol (la sezione delle note su http://msdn.microsoft.com/en-us/library/0c899ak8.aspx) – daniloquio

+0

@daniloquio Pensi di poter fornire un codice di lavoro rapido con il tuo suggerimento? Sono abbastanza sicuro di quello che stavo cercando! – heltonbiker

+0

ha modificato la mia risposta attuale con una soluzione. Si prega di dare un'occhiata – daniloquio

risposta

11

Double.ToString() utilizza NumberFormatInfo.CurrentInfo per formattare i suoi numeri. Questa ultima proprietà fa riferimento allo CultureInfo attualmente impostato sul thread attivo. Questo valore predefinito è la locale corrente dell'utente. In questo caso è un ambiente culturale portoghese. Per evitare questo comportamento, utilizzare il sovraccarico Double.ToString(IFormatProvider). In questo caso è possibile utilizzare CultureInfo.InvariantCulture.

Inoltre, è possibile semplicemente passare il simbolo NaN se si desidera mantenere tutti gli altri markup. Per impostazione predefinita, le informazioni sulla globalizzazione sono di sola lettura. La creazione di un clone aggirerà questo problema.

Per impostare questo sul thread corrente, creare una copia della cultura corrente e impostare le informazioni sul formato numero sulla cultura. Pre .NET 4.5 non c'è modo di impostarlo per tutti i thread. Dopo aver creato ciascun thread, è necessario garantire un valore corretto CultureInfo. A partire da .NET 4.5 c'è CultureInfo.DefaultThreadCurrentCulture che definisce la cultura predefinita per i thread all'interno dello AppDomain. Questa impostazione viene considerata solo quando la cultura del thread non è stata ancora impostata (vedere MSDN).

Esempio per un singolo filo:

System.Globalization.CultureInfo myCulture = 
    (System.Globalization.CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone(); 
myCulture.NumberFormat.NaNSymbol = "NaN"; 

System.Threading.Thread.CurrentThread.CurrentCulture = myCulture; 
string numString = double.NaN.ToString(); 
+1

Che non produrrà il suo output desiderato, che utilizza un separatore decimale localizzato. –

+0

Attualmente ottengo la stringa 'NaN (não é um número)'. Il mio obiettivo non è quello di ottenere 'NaN (non un numero)' ma solo il semplice 'NaN'. Come potrei ottenere questo? – heltonbiker

+0

Secondo il commento di Daniloquio, esiste la proprietà 'NumberFormatInfo.NaNSymbol', che" Ottiene o imposta la stringa che rappresenta il valore IEEE NaN (non un numero). " Quindi la mia domanda si ridurrebbe a "come posso impostare il NaNSymbol della cultura del mio thread corrente?" – heltonbiker

1

Semplicemente non passano valori NaN a ToString.

Ad esempio (avvolgendoli in un metodo di estensione per un facile riutilizzo):

static string ToCleanString(this double val) 
{ 
    if (double.IsNan(val)) return "NaN"; 
    return val.ToString(); 
} 
+0

Ho aggiornato il mio codice. In realtà il metodo 'double.NaN.ToString()' viene chiamato dall'interno del metodo 'Point3D.ToString()' ... – heltonbiker

+1

@heltonbiker: Sì, mi sono chiesto. E cambia le cose. Penso che la mia preferenza sarebbe solo quella di sostituire la chiamata 'Point3D.ToString()' con il mio metodo che converte e concatena tutti e tre i valori sotto il mio controllo. –

0

stai:

NumberFormatInfo myFormatInfo = NumberFormatInfo.InvariantInfo; 

Point3D myPoint = new Point3D(1,1,double.NaN); 
var pointString = myPoint.ToString(myFormatInfo); 
+0

separatore decimale errato ... –

0

Innanzitutto, la risposta fornita dal Caramiriel è la soluzione per avere double.NaN rappresentati da QUALSIASI stringa che potresti desiderare.

Per inciso, voglio la stringa "NaN", e qui è quello che dicono di the docsNumberFormatInfo.NaNSymbol:

La stringa che rappresenta il valore IEEE NaN (non un numero). L'impostazione predefinita per InvariantInfo è "NaN".

Poi ho capito come avere la mia pura stringa "nan" desiderato e di sbarazzarsi del separatore virgola, utilizzando il predefinito fornito da InvariantCultureInfo, aggiungendo la riga folloing poco dopo la creazione del thread corrente:

Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; 

E quello ha funzionato bene!