我如何修复“nan”在C#? [英] How do I fix "nan" in C#?

查看:129
本文介绍了我如何修复“nan”在C#?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果NaN出现在我的textBox中(计算结果)我想做什么

这是我的代码



what am I suppose to do if NaN appears in my textBox ( a result of the computation )
this is my code

namespace test
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            double na,ea,ha,nb,eb,hb,GridD,GroundD,GeoD,fs,ef;

                na = Convert.ToDouble(textBox2.Text);
                ea = Convert.ToDouble(textBox1.Text);
                ha = Convert.ToDouble(textBox3.Text);
                nb = Convert.ToDouble(textBox5.Text);
                eb = Convert.ToDouble(textBox4.Text);
                hb = Convert.ToDouble(textBox6.Text);
            fs = (ha+hb)/2;
            ef = ha - hb;
            GridD = Math.Sqrt((eb-ea)*2+(nb-na)*2);
            this.textBox7.Text = Convert.ToString(GridD);
            GroundD = GridD / fs;
            this.textBox8.Text = Convert.ToString(GroundD);
            GeoD = GroundD * ef;
            this.textBox9.Text = Convert.ToString(GeoD);
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }
    }
}





和textBox8,9,7会出现NaN?

你们可以帮忙解决这个问题吗?



我尝试过的事情:



我试图用浮动改变双倍,它根本不起作用: (



and the textBox8,9,7 will appear NaN?
can you guys help with this problem?

What I have tried:

I tried to change double with float, bit it didn't work at all :(

推荐答案

你试图取负数的平方根。解决方案涉及虚数 [ ^ ],这不能表示为简单的浮点数。



要解决此问题,请更新代码以使用 System.Numerics.Complex 结构 [ ^ ],或验证(eb-ea)* 2 +(nb-na)* 2 在尝试取平方根之前不小于零。



注意:帮自己一个忙,给控件赋予有意义的名字,而不是接受Visual Studio提供的默认名称。您可能还记得 TextBox47 现在是 ,但是当您在六个月后回到代码时,您将会忘记。 :)
You're trying to take the square root of a negative number. The solution involves imaginary numbers[^], which cannot be represented as simple floating-point numbers.

To solve the problem, either update your code to use the System.Numerics.Complex structure[^], or verify that (eb-ea)*2+(nb-na)*2 is not less than zero before trying to take its square root.

NB: Do yourself a favour and give your controls meaningful names, rather than accepting the default name provided by Visual Studio. You might remember what TextBox47 is now, but when you come back to your code in six months time, you'll have forgotten. :)


在Richard Deeming的解决方案之后,这是正确的,添加一个观察结果:



<$ c $中的表达式c> Math.Sqrt(),看起来确实如此:

After Richard Deeming's solution, which is correct, adding an observation:

The expression in the Math.Sqrt(), looks like it really wants to be:
(eb-ea)^2+(nb-na)^2



当然,C#无法做到。 C#中没有取幂运算符。

如果这真的是你想要的,请尝试类似:


which, of course, C# can't do. There's no exponentiation operator in C#.
If that's really what you intended, try something like:

double ediff = eb - ea;
double ndiff = nb - na;
GridD = Math.Sqrt((ediff * ediff) +(ndiff * ndiff));



这将显着更少效率很高,但你也可以这样做:


It would be significantly less efficient, but you could also do:

GridD = Math.Sqrt(Math.Pow(eb-ea, 2) + Math.Pow(nb-na, 2));



要么也要解决NaN问题的sqrt -ve值。



我有一套扩展方法来处理常见的,经常使用的数学运算,比如平方。


Either would also resolve the NaN issue of sqrt of -ve value.

I have a set of extension methods for dealing with common, frequently used, mathematical operations like squaring.

public static ExMath
{
    #region Basic Math operations
    /// <summary>
    /// Tests if the value is inclusively between two bounds
    /// </summary>
    /// <param name="value">the value to check</param>
    /// <param name="lowerBound">the lower bound of the inclusive range</param>
    /// <param name="upperBound">the upper bound of the inclusive range</param>
    /// <returns>true if value is inclusively between the bounds</returns>
    public static bool IsBetween<T>(this T value, T lowerBound, T upperBound) where T : IComparable<T>
    {
      return (lowerBound.CompareTo(value)) <= 0 && (value.CompareTo(upperBound)) <= 0;
    }

    /// <summary>
    /// Tests if the value is strictly between two bounds
    /// </summary>
    /// <param name="value">the value to check</param>
    /// <param name="lowerBound">the lower bound of the exclusive range</param>
    /// <param name="upperBound">the upper bound of the exclusive range</param>
    /// <returns>true if value is strictly between the bounds</returns>
    public static bool IsStrictlyBetween<T>(this T value, T lowerBound, T upperBound) where T : IComparable<T>
    {
      return (lowerBound.CompareTo(value)) < 0 && (value.CompareTo(upperBound)) < 0;
    }

    /// <summary>
    /// Squares a number
    /// </summary>
    /// <param name="value">the number to square</param>
    /// <returns>value * value</returns>
    public static int Square(this int value)
    {
      return value * value;
    }

    /// <summary>
    /// Cubes a number
    /// </summary>
    /// <param name="value">the number to cube</param>
    /// <returns>value * value * value</returns>
    public static int Cube(this int value)
    {
      return value * value * value;
    }

    /// <summary>
    /// Raises a value to an integer power
    /// </summary>
    /// <param name="x">the value</param>
    /// <param name="n">the exponent</param>
    /// <returns>x raised to the power n</returns>
    /// <remarks>There are no explicit checks for overflow.</remarks>
    public static int IPow(this int x, int n)
    {
      if (n == 0)
        return 1;
      if (n < 0)
        throw new InvalidOperationException("Cannot raise integer to negative power as integer result");
      int y = 1;
      while (n > 1)
      {
        if ((n & 1) == 1)
        {
          y *= x;
        }
        x *= x;
        n >>= 1;
      }
      return x * y;
    }

    /// <summary>
    /// Tests if the value is a valid index for testVector
    /// </summary>
    /// <param name="value">the index value to check</param>
    /// <param name="testCollection">the collection to check the index against</param>
    /// <returns>true if value is a valid index into testVector</returns>
    public static bool IsValidIndexInto<T>(this int value, ICollection<T> testCollection)
    {
      Debug.Assert(testCollection != null, "IsValidIndexInto testCollection is null");
      // Asymmetrical limits test, can't use IsBetween or IsStrictlyBetween
      return (0 <= value) && (value < testCollection.Count);
    }

    /// <summary>
    /// Squares a number
    /// </summary>
    /// <param name="value">the number to square</param>
    /// <returns>value * value</returns>
    public static float Square(this float value)
    {
      return value * value;
    }

    /// <summary>
    /// Cubes a number
    /// </summary>
    /// <param name="value">the number to cube</param>
    /// <returns>value * value * value</returns>
    public static float Cube(this float value)
    {
      return value * value * value;
    }

    /// <summary>
    /// Raises a value to an integer power
    /// </summary>
    /// <param name="x">the value</param>
    /// <param name="n">the exponent</param>
    /// <returns>x raised to the power n</returns>
    /// <remarks>There are no explicit checks for underflow, overflow or divide by zero.</remarks>
    public static float IPow(this float x, int n)
    {
      if (n == 0)
        return 1.0f;
      if (n < 0)
      {
        x = 1.0f / x;
        n = -n;
      }
      float y = 1.0f;
      while (n > 1)
      {
        if ((n & 1) == 1)
        {
          y *= x;
        }
        x *= x;
        n >>= 1;
      }
      return x * y;
    }

    /// <summary>
    /// Squares a number
    /// </summary>
    /// <param name="value">the number to square</param>
    /// <returns>value * value</returns>
    public static double Square(this double value)
    {
      return value * value;
    }

    /// <summary>
    /// Cubes a number
    /// </summary>
    /// <param name="value">the number to cube</param>
    /// <returns>value * value * value</returns>
    public static double Cube(this double value)
    {
      return value * value * value;
    }

    /// <summary>
    /// Raises a value to an integer power
    /// </summary>
    /// <param name="x">the value</param>
    /// <param name="n">the exponent</param>
    /// <returns>x raised to the power n</returns>
    /// <remarks>There are no explicit checks for underflow, overflow or divide by zero.</remarks>
    public static double IPow(this double x, int n)
    {
      if (n == 0)
        return 1.0;
      if (n < 0)
      {
        x = 1.0 / x;
        n = -n;
      }
      double y = 1.0;
      while (n > 1)
      {
        if ((n & 1) == 1)
        {
          y *= x;
        }
        x *= x;
        n >>= 1;
      }
      return x * y;
    }
    #endregion

    #region Conversion functions
    private const double RadiansDegreesFactor = System.Math.PI / 180.0;
    /// <summary>
    /// Convert Radians To Degrees
    /// </summary>
    /// <param name="radians">radians</param>
    /// <returns>degrees</returns>
    public static double RadiansToDegrees(this double radians)
    {
      return radians / RadiansDegreesFactor;
    }

    /// <summary>
    /// Convert Degrees to Radians
    /// </summary>
    /// <param name="degrees">degrees</param>
    /// <returns>radians</returns>
    public static double DegreesToRadians(this double degrees)
    {
      return degrees * RadiansDegreesFactor;
    }
    #endregion
}


The first thing to do is to set a break-point and single-step through this code, and observe at what point NaN \"exists.\"



Second, you are using Convert.ToDouble which will return a result of #0 if the conversion fails ... I don’t think that’s too useful; what if zero is a valid entry for one TextBox, but not a valid entry for another ? I strongly recommend you use Double.TryParse which will give you a boolean ’false if the conversion is not possible [^]. You’ll see ’TryParse used in the code below.



I believe in a strategy I call \"head ’em off at the pass\" which translates into: \"intercept errors and deal with them as soon as possible.\" I also mean by this: \"do not let users have initiate any action using controls which depend on valid data unless the data is valid.\"



So, for example, I might define a routine for checking all the TextBoxes of interest for valid double values:
The first thing to do is to set a break-point and single-step through this code, and observe at what point NaN "exists."

Second, you are using Convert.ToDouble which will return a result of #0 if the conversion fails ... I don't think that's too useful; what if zero is a valid entry for one TextBox, but not a valid entry for another ? I strongly recommend you use Double.TryParse which will give you a boolean 'false if the conversion is not possible [^]. You'll see 'TryParse used in the code below.

I believe in a strategy I call "head 'em off at the pass" which translates into: "intercept errors and deal with them as soon as possible." I also mean by this: "do not let users have initiate any action using controls which depend on valid data unless the data is valid."

So, for example, I might define a routine for checking all the TextBoxes of interest for valid double values:
public static class MathUtilities
{
    public static IEnumerable<double> TextBoxesToDoubles(params TextBox[] args)
    {
        double dbl;

        foreach (TextBox tbx in args)
        {
            if (! Double.TryParse(tbx.Text, out dbl))
            {
                throw new ArgumentException(string.Format("contents of {0} are not a valid double", tbx.Name));
            }

            yield return dbl;
        }
    }
}

But, before I ever invoked the static method shown above, I would make sure that each TextBox at least had some characters in it:

But, before I ever invoked the static method shown above, I would make sure that each TextBox at least had some characters in it:

TextBox[] DoubleInputTextBoxes;

private void button1_Click(object sender, EventArgs e)
{
    if (ValidateTextBoxesForDouble())
    {
       // okay now enable the Controls
       // that let the user do something
       // with all the doubles
    }
}

private bool ValidateTextBoxesForDouble()
{
    DoubleInputTextBoxes = new TextBox[]
    {
        textBox2, textBox3, textBox4, textBox5
    };

    if(DoubleInputTextBoxes.Any(tbx => tbx.Text == string.Empty))
    {
       throw new ArgumentException(string.Format("contents of one or more TextBoxes is not a valid double"));
    }

    List<double> doubles = MathUtilities.TextBoxesToDoubles(DoubleInputTextBoxes).ToList();

    return true;
}

The code shown here is just one way (among many ways) to handle/implement validation of data; I don’t claim it’s the best fit for your specific task at hand.



In terms of your specific code ... once you know you have valid data in your input TextBoxes ... I’d say you need to write multiple checks as you progress through your calculations, if, at any point, you get a value like a NaN that means you can’t get a valid result from your calculations, then stop the code right there, give the user a message, or throw an error.



Other alternatives:



1. use NumericUpDownControls instead of TextBoxes : greatly simplifies things. however, it’s true that many people just don’t like the \"look and feel\" of them.



2. create your own sub-classed TextBox (Component) designed for input of Doubles. this is typically what I use.



3. look here on CP for other numeric user input controls.

The code shown here is just one way (among many ways) to handle/implement validation of data; I don't claim it's the best fit for your specific task at hand.

In terms of your specific code ... once you know you have valid data in your input TextBoxes ... I'd say you need to write multiple checks as you progress through your calculations, if, at any point, you get a value like a NaN that means you can't get a valid result from your calculations, then stop the code right there, give the user a message, or throw an error.

Other alternatives:

1. use NumericUpDownControls instead of TextBoxes : greatly simplifies things. however, it's true that many people just don't like the "look and feel" of them.

2. create your own sub-classed TextBox (Component) designed for input of Doubles. this is typically what I use.

3. look here on CP for other numeric user input controls.


这篇关于我如何修复“nan”在C#?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆