Click here to Skip to main content
15,884,628 members
Please Sign up or sign in to vote.
5.00/5 (4 votes)
See more:
(I cannot use BOOST, C++11 or C++14 features like std::experimental::optional)

Is it good practice to use NaN to check if a double variable is assigned or not ? (if a variable value is semantically there or not)

I'm reading/parsing a XML file that contain double values; some of those values are not always used and will be "empty" in the XML file.
When writing back the value to the XML file, I don't want to write back a value if it was not assigned by my program.


<node attribute=""/> 


in my code I have something like (pseudo code)

void ReadAttribute( string attributeName, double& value )
{
  string tmp;
  ReadXLMAttribute( attributeName, tmp );
  if ( tmp.empty )
    value = std::numeric_limits<double>::quiet_NaN();
  else
    value = ConvertStringToDouble( tmp );

}

void WriteAttribute ( string attributeName, double value )
{
  string tmp;
  if ( value !- NaN )
  { 
     tmp = ConvertDoubleToString( value )
  } 
  else
  { 
     tmp = "";
  }
  WriteXMLAttribute( attributeName, tmp );

}

double attribute = std::numeric_limits<double>::quiet_NaN();

ReadAttribute ("attribute", attribute );

WriteAttribute("attribute", attribute );


Does that make sense ?

Thanks.

Max.
Posted
Comments
Sergey Alexandrovich Kryukov 12-Sep-14 22:37pm    
Good important question. My 5.
—SA

It would work but I wouldn't do that.
First of all, you know, NaN could be the result of an actual expression, hence you are giving it more meanings. Another point is you could end up (if you forgot to check it before use) performing some computation with such NaN values.
While using a struct or class with a boolean isValid llooks like wasting resources, it is, in my opinion a cleaner and painless approach (for instance you could automate validity check before use it in expressions).
 
Share this answer
 
Comments
Maximilien 12-Sep-14 10:37am    
Thanks, I was toying with the idea of using a bool for the values (not just double values).
Sergey Alexandrovich Kryukov 12-Sep-14 22:40pm    
The question is really good and important. And the idea if using NaN is also very good.

Carlo,

Will you tell me: is 0.0 (the result of default initialization) any better? It's a number, but sometimes we really need to express the idea of not a number. How can you tell 0.0 as initial value from 0.0 as a result of some computing? That's why the value is a part of IEEE 754 standard. Please see my answer where I try to explain the importance of using NaN. (And +Inf and -Inf are also very important).

—SA
CPallini 13-Sep-14 0:43am    
In my opinion, Nullable is the right answer here. Neither NaN nor the default initializer are good replacements for Nullable.
In practice, using NaN is viable but then he has to be very careful.
Sergey Alexandrovich Kryukov 13-Sep-14 9:45am    
Nullable is good for types which have no such reserved values as NaN... If NaN works, it a benefit to performance.
—SA
CPallini 13-Sep-14 13:11pm    
Nan is not reserved for representing null. However, if performance is an issue you are right. It is worth noting the OP has the same problem also on different types.
I am sure this practice is good enough, but then you should always assign NaN at the moment of initialization.

More exactly, you should use Not a Number to conduct the idea of not a number, whatever it is. C Pallini is right: it can be a result of arithmetic operation. But there are cases when you really can initialize the value with NaN. It depends on what you do.

One good example: you have an array of values; and then data acquisition fills it with values. Some measurement may fail, and then you present the data somehow. How the values should be initialized? If you initialize them by default, the default is 0.0. But the measurements can give you 0.0, too, so how it could be different from not initialized value (say, failed measurement)? So, NaN is certainly better. (More exactly, default initialization with 0.0 is simply unacceptable.)

You should also remember that NaN is quite legitimate, because of the standard IEEE 754: http://en.wikipedia.org/wiki/IEEE_floating_point[^].

—SA
 
Share this answer
 
What makes sense depends on what your application needs to achieve:

- do the internal operations need to discern unassigned values from values that are the result of processing?

- do you need to distinguish unassigned, infinite, underflow, zero, or NaN values? Do you need to properly represent these states in output too? (see http://www.cplusplus.com/reference/cmath/fpclassify/[^] for more info)

- can the internal processes even deal with unassigned numbers or do they always need a valid value? If so, is there a reasonable default value for unassigned numbers?

- Is there a need to reproduce exactly the same output as you are reading if nothing is changed?

- are there any range limitations that you can take advantage of for the purpose of defining magic numbers that represent certain states such as being unassigned?

The most general solution would be to maintain a separate flag for each value that indicates its current state. The advantage is that you can define an arbitrary number of states and use it for any specific type, without restrictions. The disadvantages are the added requirements for memory, processing, and code.

A second option would be to (ab)use any of the other possible states of a variable as an indicator. The disadvantage is the inability to discern whether a variable in that state was simply unassigned or arrived at that value through processing.

A third option would be to define a specific normal value that represents the unassigned state: this obviously only works, if you can make sure that value is not within the normal valid range of values for any variable of that type. It is therefore not that practical, in most cases. It is also somewhat tricky to exactly compare a floating point value to a given constant.
 
Share this answer
 

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

  Print Answers RSS
Top Experts
Last 24hrsThis month


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