Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does C# TryParse not handle NaN?

Tags:

c#

tryparse

I have some common methods for parsing with default value overrides when reading in some old Fortran data. Occasionally the data has NaN (Not a number) where there should be a numeric value. I expected that the TryParse would see the string "NaN" and fail to parse. However, TryParse successfully parses and places NaN in for the numeric value. Is this expected behavior? If this is expected, are there any other "gotcha" values that I should be looking for?

    public static double GetDoubleFromString(string s, double defaultOnFailure = 0)
    {
        //Must be here due to TryParse returning NaN to d and result is set to true below
        if (s.Contains("NaN"))
        {
            log.Warn(string.Format("String contained NaN, returning defaultOnFailure {0} string was {1}", defaultOnFailure, s));
            return defaultOnFailure;
        }

        var d = defaultOnFailure;
        if (!double.TryParse(s.Trim(), out d))
        {
            log.Warn(string.Format("Failed to parse double from string returning defaultOnFailure {0} string was {1}", defaultOnFailure, s));
        }

        return d;
    }

UPDATE

I feel that it should be mentioned, that this only happens for double, long and int do not return the NaN value. See the example code below, the Common.... code is just formatted Console.WriteLine or stops for console execution. See screenshot below for output.

    public static void NanTestMain()
    {
        Common.WriteBlankWithTitle("Test parse NaN");
        string s = "NaN";

        Common.WriteBlankWithTitle("NaN to Int");
        int i;
        var intSuccess = int.TryParse(s, out i);
        Console.WriteLine(string.Format("Int parse of {0} parse = {1}", i, intSuccess));

        Common.WriteBlankWithTitle("NaN to Double");
        double d;
        var doubleSuccess = double.TryParse(s, out d);
        Console.WriteLine(string.Format("Double parse of {0} parse = {1}", d, doubleSuccess));

        Common.WriteBlankWithTitle("NaN to Long");
        long l;
        var longSuccess = long.TryParse(s, out l);
        Console.WriteLine(string.Format("Long parse of {0} parse = {1}", l, longSuccess));

        Common.Pause();
    }

Results of Update Code

like image 253
JabberwockyDecompiler Avatar asked Oct 25 '25 06:10

JabberwockyDecompiler


2 Answers

From MSDN:

The s parameter can contain NumberFormatInfo.PositiveInfinitySymbol, NumberFormatInfo.NegativeInfinitySymbol, or NumberFormatInfo.NaNSymbol for the culture indicated by provider.

There are three "special" values to look out for. However, the last few words are key - depending on the current culture, you might see something other than "NaN"!

like image 142
Jacob Krall Avatar answered Oct 26 '25 18:10

Jacob Krall


Double.NaN is a valid value for a double, so this is normal. There is also negative and positive infinity. Check here for other possible 'special' values.

like image 28
Saragis Avatar answered Oct 26 '25 19:10

Saragis