Search code examples
c#c++doublestd

How to check in C# if the given double number is normal, i.e. is neither zero, subnormal, infinite, nor NaN


How to check in C# if the given double number is normal, i.e. is neither zero, subnormal, infinite, nor NaN.

In C++ there was a method std::isnormal which was exactly checking this condition. Is there an equivalent in C#?


Solution

  • Mathias gave the basic approach to detecting subnormal values in a comment. Here it is coded up:

    const long ExponentMask = 0x7FF0000000000000;
    static bool IsSubnormal(double v)
    {
        if (v == 0) return false;
        long bithack = BitConverter.DoubleToInt64Bits(v);
        return (bithack & ExponentMask ) == 0;
    }
    
    static bool IsNormal(double v)
    {
        long bithack = BitConverter.DoubleToInt64Bits(v);
        bithack &= ExponentMask;
        return (bithack != 0) && (bithack != ExponentMask);
    }
    

    And now it's been tested. Test suite:

    static void TestValue(double d)
    {
        Console.WriteLine("value is {0}, IsSubnormal returns {1}, IsNormal returns {2}", d, IsSubnormal(d), IsNormal(d));
    }
    
    static void TestValueBits(ulong bits)
    {
        TestValue(BitConverter.Int64BitsToDouble((long)bits));
    }
    
    public static void Main(string[] args)
    {
        TestValue(0.0);
        TestValue(1.0);
        TestValue(double.NaN);
        TestValue(double.PositiveInfinity);
        TestValue(double.NegativeInfinity);
        TestValue(double.Epsilon);
        TestValueBits(0xF000000000000000);
        TestValueBits(0x7000000000000000);
        TestValueBits(0xC000000000000000);
        TestValueBits(0x4000000000000000);
        TestValueBits(0xFFF0000000000005);
        TestValueBits(0x7FF0000000000005);
        TestValueBits(0x8010000000000000);
        TestValueBits(0x0010000000000000);
        TestValueBits(0x8001000000000000);
        TestValueBits(0x0001000000000000);
    }
    

    Demo: https://rextester.com/CMFOR3934