Come modificare la rappresentazione della stringa NaN in C #?

Il mio programma salva un pointcloud su file, dove ogni pointcloud è Point3D[,] , dallo spazio dei nomi System.Windows.Media.Media3D . Questo mostra una riga del file di output (in portoghese):

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

mentre mi piacerebbe che fosse (al fine di essere analizzato correttamente in seguito):

 -112,644088741971;71,796623005014;NaN 

Il blocco di codice che genera il file è qui:

 var lines = new List(); 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 da Point3D.ToString() , includa quella “spiegazione aggiuntiva” tra parentesi che non desidero affatto.

C’è un modo per cambiare / sovrascrivere questo metodo in modo che generi solo NaN , senza la parentesi?

Double.ToString() utilizza NumberFormatInfo.CurrentInfo per formattare i suoi numeri. Questa ultima proprietà fa riferimento a 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 l’ Double.ToString(IFormatProvider) . In questo caso puoi utilizzare CultureInfo.InvariantCulture .

Inoltre puoi semplicemente cambiare il simbolo NaN se vuoi conservare tutti gli altri markup. Per impostazione predefinita, le informazioni sulla globalizzazione sono di sola lettura. La creazione di un clone aggirerà questo problema.

 System.Globalization.NumberFormatInfo numberFormatInfo = (System.Globalization.NumberFormatInfo) System.Globalization.NumberFormatInfo.CurrentInfo.Clone(); numberFormatInfo.NaNSymbol = "NaN"; double num = double.NaN; string numString = System.Number.FormatDouble(num, null, numberFormatInfo); 

Per impostarlo sul thread corrente, crea una copia della cultura corrente e imposta le informazioni sul formato numerico sulla cultura. Pre. NET 4.5 non c’è modo di impostarlo per tutti i thread. Dopo aver creato ciascun thread, dovresti assicurarti un CultureInfo corretto. A partire da .NET 4.5 c’è CultureInfo.DefaultThreadCurrentCulture che definisce la cultura di default per i thread all’interno di AppDomain . Questa impostazione viene considerata solo quando la cultura del thread non è stata ancora impostata (vedere MSDN).

Esempio per un singolo thread:

 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(); 

Semplicemente non passare i valori NaN a ToString .

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

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

Che ne dite di:

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

Prima di tutto, la risposta fornita da Caramiriel è la soluzione per avere double.NaN rappresentato da QUALSIASI stringa che potresti desiderare.

Per inciso, voglio la stringa "NaN" , ed ecco cosa dicono i documenti su NumberFormatInfo.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” desiderata E sbarazzarmi del separatore di virgola, usando l’impostazione predefinita fornita da InvariantCultureInfo , aggiungendo la linea di distribuzione subito dopo la creazione del thread corrente:

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

E quello ha funzionato bene!