Click here to Skip to main content
15,885,537 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
what am I suppose to do if NaN appears in my textBox ( a result of the computation )
this is my code

C#
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)
        {

        }
    }
}


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 :(
Posted
Updated 26-May-16 8:35am
Comments
Alan N 26-May-16 13:40pm    
Have you read the documentation for Math.Sqrt? It may help you.
Sergey Alexandrovich Kryukov 26-May-16 13:58pm    
What would it mean, "fix NaN"? NaN is a legitimate value, it's not something which can be fixed. If NaN is the result of a bug, you should fix the bug, but sometimes it's not a bug but a result of correct calculations.
—SA

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. :)
 
Share this answer
 
v2
Comments
Sergey Alexandrovich Kryukov 26-May-16 14:01pm    
5ed. It's a good suggestion to change the problem into a problem with complex numbers.

I would only add that NaN is quite a legitimate object. Say, if a user enters arbitrary coefficients of the squared equations and software is supposed to find the roots, in real numbers, NaN would be a correct answer for some coefficients (input data).

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

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

which, of course, C# can't do. There's no exponentiation operator in C#.
If that's really what you intended, try something like:
C#
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:
C#
GridD = Math.Sqrt(Math.Pow(eb-ea, 2) + Math.Pow(nb-na, 2));

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.
C#
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
}
 
Share this answer
 
v3
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:
C#
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:
C#
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.
 
Share this answer
 
v2
Convert.ToAnything usage is generally the sign of a bad design.
You have to ensure that the input string is actually a valid string representation for a double; when you know that there are almost as many ways of representing numbers as there are cultures on Earth, you have an idea of the non-triviality of the task. Moreover, as a developer, you should never use values obtained from user inputs without validating them before.

Best way here would be to use TryParse method; here is an example for your na variable, you just have to follow the pattern for other variables:
C#
double na;
if (!double.TryParse(textBox2.Text, out na)) {
   // If you get here then there is a problem with the text in textBox2.
   // Maybe assign a default value? Or throw an exception? It's up to you...
}

And:
C#
this.textBox7.Text = Convert.ToString(GridD);

is ugly and should be replaced by:
C#
this.textBox7.Text = GridD.ToString();

A few other things:
- there are a lot of reasons for the string -> double parsing to fail; user may have entered a point (or something else) as decimal separator, whereas the computers thinks decimal separator is another character, or doesn't expect any decimal separator at all. Or there are some invalid signs in the string which makes its totally impossible to parse...
- you should give your control (textboxes) meaningful names instead of default ones ; this would make your code much easier to read and maintain.
- you should search for "c# debugging tutorial", or something equivalent, in your favorite search-engine. Debugging is far from being optional, if you take development as a serious task. This[^] could be a great place to start.

Kindly.
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 26-May-16 18:34pm    
By the way... Good points, a 5.
—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900