代码之家  ›  专栏  ›  技术社区  ›  Trap

当任何数学运算产生“nan”时,如何强制C编译器抛出异常?

  •  5
  • Trap  · 技术社区  · 15 年前

    我最近编写的程序中的一些数学函数返回了不可接受的值,比如NaN(可能是因为没有检查某些函数的输入参数)。问题是很难追踪哪些函数传递了错误的值。这会导致错误在整个代码中传播,并使程序在几分钟或几小时后崩溃(如果有的话)。

    我不知道是否有一种方法来捕捉这些错误的操作的时刻,一个NaN值的结果,任何操作(几乎相同的'除法零异常'抛出一些C/C++编译器,如果我记得)。

    事先谢谢。

    P.D:如果需要,请随时重新标记我的问题。

    6 回复  |  直到 11 年前
        1
  •  9
  •   ChrisF    15 年前

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

        2
  •  7
  •   Michael Brandl    11 年前

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

        3
  •  5
  •   Alexander Torstling    15 年前

    _controlfp_s

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

    errno_t err = _controlfp_s(0, _oldState, MCW_EM);
    assert(!err);
    
        4
  •  3
  •   Steve    15 年前

    int NaN checked

    #if DEBUG

        5
  •  1
  •   user    11 年前

    TIntegerType SafeInt

        6
  •  0
  •   Community CDub    7 年前