Как изменить строковое представление NaN в C#?

моя программа сохраняет pointcloud в файл, где каждый pointcloud является Point3D[,] С System.Windows.Media.Media3D пространство имен. Это показывает строку выходного файла (на португальском языке):

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

в то время как я хотел бы, чтобы это было (для того, чтобы быть правильно разобранным впоследствии):

-112,644088741971;71,796623005014;NaN

блок кода, который генерирует файл здесь:

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

кажется double.NaN.ToString() метод, вызванный изнутри Point3D.ToString(), включает это заключенное в скобки "дополнительное объяснение", которое я совсем не хочу.

есть ли способ изменить / переопределить этот метод, чтобы он выводил только NaN, без скобок часть?

4 ответов


Double.ToString() использует NumberFormatInfo.CurrentInfo формат его номера. Это последнее свойство ссылается на CultureInfo, который в настоящее время установлен в активном потоке. По умолчанию используется текущая локаль пользователя. В этом случае это португальская культура. Чтобы избежать такого поведения, используйте Double.ToString(IFormatProvider) перегрузка. В этом случае вы можете использовать CultureInfo.InvariantCulture.

кроме того, вы можете просто переключить символ NaN, если хотите сохранить всю другую разметку. По умолчанию информация о глобализации доступна только для чтения. Создание клон справится с этим.

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

чтобы установить это в текущем потоке, создайте копию текущей культуры и задайте информацию о числовом формате в культуре. Pre .NET 4.5 нет способа установить его для всех потоков. После создания каждого потока вам нужно будет убедиться в правильности CultureInfo. Начиная с .NET 4.5 есть CultureInfo.DefaultThreadCurrentCulture, который определяет культуру по умолчанию для потоков в пределах AppDomain. Этот параметр учитывается только в том случае, если культура потока не была задана установите еще (см. MSDN).

пример для одного потока:

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

просто не передавайте значения NaN в ToString.

например (упаковка в метод расширения для повторного использования):

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

Как насчет:

NumberFormatInfo myFormatInfo = NumberFormatInfo.InvariantInfo;

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

прежде всего, ответ, предоставленный Caramiriel является решением иметь double.NaN представлен любой строкой, которую вы можете пожелать.

кстати, я хочу строку "NaN" и документы говорить о NumberFormatInfo.NaNSymbol:

строка, представляющая значение IEEE NaN (не число). Значение по умолчанию для InvariantInfo - "NaN".

затем я понял, как получить желаемую чистую строку " NaN " и избавиться от запятой сепаратор, с помощью по умолчанию InvariantCultureInfo, добавив складывающуюся строку сразу после создания текущего потока:

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

и это сработало отлично!