9

What are the benefits of NaN, PositiveInfinity or NegativeInfinity for float and double? When should we use or avoid them?

If there are constants like these, why does float.Parse("a") throw an error rather than returning float.NaN?

How is NaN different than null? Why is division by zero even possible for floating types?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
LZW
  • 1,035
  • 2
  • 10
  • 13
  • you could use TryParse rather than Parse? – Liam Feb 27 '13 at 16:46
  • 2
    Used because of math operations. – Ievgen Feb 27 '13 at 16:46
  • 8
    @Evgeny: vaguest comment ever. – Robert Harvey Feb 27 '13 at 16:49
  • 2
    @Liam my question wasn't about how to parse, I would like to know why there is NaN in a strongly typed environment. – LZW Feb 27 '13 at 18:10
  • possible duplicate of [what does NaN mean for doubles?](http://stackoverflow.com/questions/8112529/what-does-nan-mean-for-doubles) – nawfal Jan 27 '14 at 09:30
  • Also, Parse failing does not necessarily mean that the value is Not a Number. For example, it will fail with Unicode digits http://www.fileformat.info/info/unicode/category/Nd/list.htm `.Parse("1")` or with some different culture settings – Slai Oct 27 '16 at 12:39

5 Answers5

12

Infinities are used because they are part of the arithmetic system supported by floating point. There are various operations, such as dividing by zero, in which infinity is a useful result and is mathematically sensible. Obviously, no direct physical quantity can be infinite (you cannot have infinitely many grams, for example), but infinity may be a useful value for some aspect of a mathematical model of physical processes or other things that humans model with computers.

NaNs are used because the arithmetic system is incomplete. That is, there are operations with input values for which the proper mathematical result is not representable within floating point. For example, sqrt(-1) is a legitimate mathematical operation, but the result, the imaginary number i, is not representable in floating point. So NaN is used as a placeholder to indicate that the values have gone outside the floating point numbers. NaN can also be used for other purposes, such as marking data that is not otherwise initialized, to help with debugging.

float.Parse("a") throws an error rather than returning a NaN because it is a not a legitimate operation. This expression does not perform a mathematical operation that has a proper result outside the representable numbers. It is an actual error, so it throws an error.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • I like this answer; it explains why Parse fails, as you basically are trying to unify two types that have no relationship (float and string) – JerKimball Feb 27 '13 at 19:35
9

They are not so much something you use as they are something you need to be aware of:

double hmm = 1.0 / 0.0;
double hmm2 = -1.0 / 0.0;
double hmm3 = 0.0 / 0.0;
Console.WriteLine("1/0 == {0}", hmm);
Console.WriteLine("-1/0 == {0}", hmm2);
Console.WriteLine("0/0 == {0}", hmm3);

Output:

1/0 == Infinity
-1/0 == -Infinity
0/0 == NaN

EDIT: As for this question:

If there are constants like these, why does float.Parse("a") throw an error rather than returning float.NaN?

double.NaN is actually a mathematical definition in a way - it is "defined" as 0.0/0.0 - while the words "not a number" imply that something like double.Parse("a") should also return double.NaN, it does not. Why?

My hunch is because it would be impossible to determine if the double.NaN you received was the result of garbage data (in the case of the string) or the actual definition of an indeterminate number, like zero divided by zero. So, to make a distinction between these two cases, double.Parse("a") throws an Exception, which I feel is more accurate.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
JerKimball
  • 16,584
  • 3
  • 43
  • 55
  • Why division by zero is possible for floating types? – LZW Feb 27 '13 at 18:16
  • 1
    @LZW Simple answer: because you can type/compile/run `1.0/0.0` - in olden days, this would cause a `DivideByZeroException`, but there are theoretical applications for "defined" `Infinity` and `NaN` values - for example, WPF uses both of these to signify "unset" or "undefined" sizes, etc. – JerKimball Feb 27 '13 at 18:26
  • @LZW: In many cases, determining *whether* a floating-point expression could be evaluated without any intermediate computations going out of range would require computations that are more expensive than those necessary to evaluate the expression when everything is in range. Allowing code to try to evaluate the expression and then find out if there was a problem is thus cheaper than requiring code to detect problematic conditions in advance. – supercat Feb 19 '15 at 03:52
6

If there are constants like these why float.Parse("a") throw error rather than returning float.NaN?

Because neither of the alternatives you listed are applicable here:

PositiveInfinity and NegativeInfinity are just that – i.e. they are the result of expressions such as 1/0 or -1/0.

NaN is the result of 0/0 – that is, an expression whose result is not (normally) well-defined and doesn’t result in a number.

float.Parse("a") is nothing like that. Admittedly, it could potentially be represented by NaN but then you couldn’t distinguish between the user entering an invalid float value (a) and a valid float value (NaN). This is not a very strong argument, however: NaN is explicitly a placeholder for an invalid number so it could conceivably be used to represent invalid user input.

On the other hand, there are other types which have a Parse method and for which no NaN value exists (such as int). For these types, Parse must therefore signal an error. It would be inconsistent (and therefore bad API design) to make different types’ Parse method behave differently.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
1

Apart from the results from arithmetic, the infinity values can be used to define no limits for a context.

For example: A Parent WPF Control asking one of its children to measure itself, under the context that there is no size restriction; i.e. availableSize is PositiveInfinity

Ref: MeasureOverride

Meirion Hughes
  • 24,994
  • 12
  • 71
  • 122
-1

To resolve NAN and infinity, use this:

if (Double.IsNaN(YourValue) || Double.IsInfinity(YourValue))
{
   YourValue = 0;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131