How can I declare a nan literal?

Started by
6 comments, last by Matias Goldberg 8 years, 5 months ago

My goal is to declare a nan literal so that when a position is not defined.

It will give it something like

D3DXVECTOR3(nan, nan, nan)

so I get some basic idea what is going on.

Are there any easy ways to achieve this?

Thanks

Jack

Advertisement
std::numeric_limits<double>::quiet_NaN() is a bit of a mouthful, but it's probably what you need.

#include <limits>

const double nan = std::numeric_limits<double>::quiet_NaN();

I shall mention defaulting your floats to NaN is a bad idea.

They have the habit of spreading around like a plague (since almost any operation with a NaN returns a NaN). One forgotten NaN can cause you to see thousands of NaNs everywhere on somewhere on an almost completely unrelated section of code.

Furthermore NaNs often cause physics engines to crash. So you will get cryptic crashes inside the physics engine which you probably won't have the source code (e.g. PhysX, Havok) with little clue that you're the one causing the problem with a NaN initialized a long time ago.

But worst sin of all; NaNs are incredibly useful for finding uninitialized variables. I often override all allocators (new, malloc, etc) and initialize all the range of memory I return to signaling NaNs. Then make sure the control word is set to signal exceptions on any NaN.

When an uninitialized value is used, bam! exception raised, problem found.

If you use NaNs explicitly around all of your codebase, this technique becomes useless since every time you initialize a float with a NaN you'll get a false positive.

Also NaNs can hit the performance. CPUs rarely operate at 100% speed when NaNs are involved.

Use a more sane value, like 0 or 1.

Or some value beyond the size of your world perhaps

float.max, float.min maybe?

I recommend just sticking to the origin (0,0,0) for default positions. It's easy enough to see what's going on when all game objects end up floating in the middle of a level or whatnot.

Matias explains well why NaN is a bad idea. Using large numbers has other "viral" properties that are hard to detect. Very small numbers are morally equivalent to just using zero. Objects will very rarely _actually_ want to be at the origin, so it works well.

Sean Middleditch – Game Systems Engineer – Join my team!

But worst sin of all; NaNs are incredibly useful for finding uninitialized variables. I often override all allocators (new, malloc, etc) and initialize all the range of memory I return to signaling NaNs. Then make sure the control word is set to signal exceptions on any NaN.

When an uninitialized value is used, bam! exception raised, problem found.

If you use NaNs explicitly around all of your codebase, this technique becomes useless since every time you initialize a float with a NaN you'll get a false positive.

Also NaNs can hit the performance. CPUs rarely operate at 100% speed when NaNs are involved.

A bit confused here, isn't using NaN's for finding uninitialized variables what he is trying to do? Or does even assignment of signaling NaN's cause an exception (I was under the impression they were fine till you tried to do a calculation)?

A bit confused here, isn't using NaN's for finding uninitialized variables what he is trying to do?

My interpretation is asked how to do:
float x = NaN;
doSomething( x );
Which is different from overriding the memory allocators so that all the memory chunks returned are initialized to the pattern 7fe00001.

Or does even assignment of signaling NaN's cause an exception (I was under the impression they were fine till you tried to do a calculation)?

That's usually the case however generated assembly out of C/C++ often does more than just a single fld/fst or movss thus triggering the exception anyway.

This topic is closed to new replies.

Advertisement