How to force the C # compiler to throw an exception when any mathematical operation produces "NaN"?

Some mathematical functions in a program I wrote recently return unacceptable values, such as NaN (possibly due to the fact that some input parameters of the function are not checked). The problem is that it’s pretty hard to keep track of which functions pass the wrong values. This leads to the fact that errors propagate throughout the code and lead to a malfunction of the program minutes or hours later, if at all possible.

I wonder if there is a way to catch these erroneous operations at the moment when the NaN value is the result of some operation (almost the same as in the case of the DivisionByZero exception created by some C / C ++ compilers, if I remember).

Thanks in advance.

PD: Please feel free to re-tag my question if necessary.

+5
source share
6 answers

Without looking at the code, this answer will be unclear, but one way to do this is to check the output from your function, and if it is "NaN" raise and exclude:

if (double.IsNaN(result))
{
    throw new ArithmeticException();
}

But with more details on the exception.

UPDATE

To trap where a particular exception is thrown, you can (temporarily) break when the exception is thrown in the debugger.

Select Debug> Exceptions , then expand the tree to select Common Language Exceptions> System> System.ArithmeticException and select the Thrown check box.

, , , . .

+9

, : Alexander Torstling .

, # , ( ++ ).

# - :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace ConsoleApplication2
{
  class Program
  {
    [System.Runtime.InteropServices.DllImport("msvcrt.dll")]
    public static extern uint _control87(uint a, uint b);

    [System.Runtime.InteropServices.DllImport("msvcrt.dll")]
    public static extern uint _clearfp();

    static void Main(string[] args)
    {
      float zero = 0.0f - args.Length; // Want 0.0f. Fool compiler...
      System.Console.WriteLine("zero = " + zero.ToString());

      // A NaN which does not throw exception
      float firstNaN = zero / 0.0f;
      System.Console.WriteLine("firstNaN= " + firstNaN.ToString());

      // Now turn on floating-point exceptions
      uint empty = 0;
      uint cw = _control87(empty, empty); // Debugger halts on this one and complains about false signature, but continue works.
      System.Console.WriteLine(cw.ToString());
      uint MCW_EM = 0x0008001f; // From float.h
      uint _EM_INVALID = 0x00000010; // From float.h (invalid corresponds to NaN
      // See http://www.fortran-2000.com/ArnaudRecipes/CompilerTricks.html#x86_FP

      cw &= ~(_EM_INVALID);
      _clearfp(); // Clear floating point error word.
      _control87(cw, MCW_EM); // Debugger halts on this one and complains about false signature, but continue works.      
      System.Console.WriteLine(cw.ToString());

      // A NaN which does throw exception
      float secondNaN = 0;
      try
      {
        // Put as much code here as you like.
        // Enable "break when an exception is thrown" in the debugger
        // for system exceptions to get to the line where it is thrown 
        // before catching it below.
        secondNaN = zero / 0.0f;
      }
      catch (System.Exception ex)
      {
        _clearfp(); // Clear floating point error word.
      }      

      System.Console.WriteLine("secondNaN= " + secondNaN.ToString());
    }
  }
}

, , { " ".} System.Exception {System.ArithmeticException}

, _control87; ? "" .

+7

, CLR, _ controlfp_s :

unsigned int _oldState;
errno_t err = _controlfp_s(&oldState, 0, MCW_EM);
assert(!err);

reset:

errno_t err = _controlfp_s(0, _oldState, MCW_EM);
assert(!err);
+5

, - , int NaN, , ? , . checked, , .

, , ChrisF. #if DEBUG , , .

+3

, , int ( double), int ( double). NaN (N.B. , int double).

, int ( double, ). TIntegerType , , int SafeInt.

-, , (, , , ).

+1

, , - :

, , .

0

All Articles