The Framework can represent two very special values, which may not be numeric values themselves but are produced by numeric calculations: NaN (not a number) and Infinity. If your calculations produce NaN or Infinity, you should confirm the data and repeat the calculations, or give up. For all practical purposes, neither NaN nor Infinity can be used in everyday business calculations.
Not a Number (NaN)
NaN is not new. Packages such as Wolfram Mathematica and Microsoft Excel have been using it for years. The value NaN indicates that the result of an operation can’t be defined: It’s not a regular number, not zero, and not infinity. NaN is more of a mathematical concept rather than a value you can use in your calculations. The Log() function, for example, calculates the logarithm of positive values. By definition, you can’t calculate the logarithm of a negative value. If the argument you pass to the Log() function is a negative value, the function will return the value NaN to indicate that the calculations produced an invalid result. You may find it annoying that a numeric function returns a non-numeric value, but it’s better than throwing an exception. Even if you don’t detect this condition immediately, your calculations will continue and they will all produce NaN values.
Some calculations produce undefined results, such as infinity. Mathematically, the result of dividing any number by zero is infinity. Unfortunately, computers can’t represent infinity, so they produce an error when you request a division by zero. VB 2008 will report a special value, which isn’t a number: the Infinity value. If you call the ToString method of this value, however, it will return the string Infinity. Let’s generate an Infinity value. Start by declaring a Double variable, dblVar:
Dim dblVar As Double = 999
Then divide this value by zero:
Dim infVar as Double
infVar = dblVar / 0
Code language: VB.NET (vbnet)
and display the variable’s value:
MsgBox(infVar)
Code language: VB.NET (vbnet)
The string Infinity will appear in a message box. This string is just a description; it tells you that the result is not a valid number (it’s a very large number that exceeds the range of numeric values that can be represented with any data type), but it shouldn’t be used in other calculations. However, you can use the Infinity value in arithmetic operations. Certain operations with infinity make sense; others don’t. If you add a number to infinity, the result is still infinity (any number, even an arbitrarily large one, can still be increased). If you divide a value by infinity, you’ll get the zero value, which also makes sense. If you divide one Infinity value by another Infinity value, you’ll get the second odd value, NaN.
Another calculation that will yield a non-number is the division of a very large number by a very small number. If the result exceeds the largest value that can be represented with the Double data type, the result is Infinity. Declare three variables as follows:
Dim largeVar As Double = 1E299
Dim smallVar As Double = 1E-299
Dim result As Double
Code language: VB.NET (vbnet)
The notation 1E299 means 10 raised to the power of 299, which is an extremely large number. Likewise, 1E-299 means 10 raised to the power of −299, which is equivalent to dividing 10 by a number as large as 1E299.
Then divide the large variable by the small variable and display the result:
result = largeVar / smallVar
MsgBox(result)
Code language: VB.NET (vbnet)
The result will be Infinity. If you reverse the operands (that is, you divide the very small by the very large variable), the result will be zero. It’s not exactly zero, but the Double data type can’t accurately represent numeric values that are very, very close to zero.
You can also produce an Infinity value by multiplying a very large (or very small) number by itself many times. But clearly, the most absurd method of generating an Infinity value is to assign the Double.PositiveInfinity or Double.NegativeInfinity value to a variable!
The result of the division 0 / 0, for example, is not a numeric value. If you attempt to enter the statement 0 / 0 in your code, however, VB will catch it even as you type, and you’ll get the error message Division by zero occurs in evaluating this expression.
To divide zero by zero, set up two variables as follows:
Dim var1, var2 As Double
Dim result As Double
var1 = 0
var2 = 0
result = var1 / var2
MsgBox(result)
Code language: VB.NET (vbnet)
If you execute these statements, the result will be NaN. Any calculations that involve the result variable will yield NaN as a result. The following statements will produce a NaN value:
result = result + result
result = 10 / result
result = result + 1E299
MsgBox(result)
Code language: VB.NET (vbnet)
If you make var2 a very small number, such as 1E-299, the result will be zero. If you make var1 a very small number, the result will be Infinity.
For most practical purposes, Infinity is handled just like NaN. They’re both numbers that shouldn’t occur in business applications (unless you’re projecting the national deficit in the next 50 years), and when they do, it means that you must double-check your code or your data.
They are much more likely to surface in scientific calculations, and they must be handled with the statements described in the next section.
Testing for Infinity and NaN
To find out whether the result of an operation is a NaN or Infinity, use the IsNaN and IsInfinity methods of the Single and Double data types. The Integer data type doesn’t support these methods, even if it’s possible to generate Infinity and NaN results with integers. If the IsInfinity method returns True, you can further examine the sign of the Infinity value with the IsNegativeInfinity and IsPositiveInfinity methods.
In most situations, you’ll display a warning and terminate the calculations. The statements of Listing 2.2 do just that. Place these statements in a button’s Click event handler and run the application.
Listing 2.2: Handling NaN and Infinity Values
Dim var1, var2 As Double
Dim result As Double
var1 = 0
var2 = 0
result = var1 / var2
If Double.IsInfinity(result) Then
If Double.IsPositiveInfinity(result) Then
MsgBox("Encountered a very large number. Can't continue")
Else
MsgBox("Encountered a very small number. Can't continue")
End If
Else
If Double.IsNaN(result) Then
MsgBox("Unexpected error in calculations")
Else
MsgBox("The result is : " & result.ToString)
End If
End If
Code language: VB.NET (vbnet)
This listing will generate a NaN value. Set the value of the var1 variable to 1 to generate a positive Infinity value, or to −1 to generate a negative Infinity value. As you can see, the IsInfinity, IsPositiveInfinity, IsNegativeInfinity, and IsNaN methods require that the variable be passed as an argument.
If you change the values of the var1 and var2 variables to the following values and execute the application, you’ll get the message Encountered a very large number:
var1 = 1E+299
var2 = 1E-299
Code language: VB.NET (vbnet)
If you reverse the values, you’ll get the message Encountered a very small number. In any case, the program will terminate gracefully and let you know the type of problem that prevents the completion of the calculations.