tags:

views:

240

answers:

6

Is it safe to cast a UINT64 to a float? I realize that UINT64 does not hold decimals, so my float will be whole numbers. However, my function to return my delta-time returns a UINT64, which isn't a very useful type for the function I'm currently working with. I'm assuming a simple static_cast<float>(uint64value) will not work?

+4  A: 

Large values of UINT64, (an 8 byte value) may be truncated if you cast them to a float, which is only 4 bytes.

Charles Salvia
Valid point. If we manually control the value (I am using it to keep track of time, so it is being capped at a relatively small value), is it possible to make this cast?
Chris
Sure. For smaller values there should be no problem.
Charles Salvia
wait, but this is a static_cast he's asking about, not a reinterpret or a union. I'm lost...
Doug T.
For natural numbers than 2^24 (16777216), there's a one-to-one mapping into 32-bit floats. If it's larger, you will lose precision.
jleedev
+4  A: 

Define safe - you can easily lose a lot of digits of precision if the 64-bit value is large, but apart from that (which is presumably a known issue that you don't mind about), the conversion should be safe. If your compiler doesn't handle it correctly, get a better compiler.

Jonathan Leffler
A: 

why wouldn't static_cast work?

Max uint64 is 2^64 = 1.84467441 × 10^19

According to this max 32-bit float is

9.999999×10^96.

Should work... having problems?

http://en.wikipedia.org/wiki/Decimal32%5Ffloating-point%5Fformat

Doug T.
The maximum is not the issue, it's the precision. You cannot take a 64-bit data type and store it in a 32-bit data type without loss of precision (e.g., the ability to tell the difference between (2^64)-3 and (2^64)-4). There are 2^64 possible int64s. There are 2^32 possible floats (less really, because of all the NaNs and Infs).
paxdiablo
Hmm I had assumed a loss of precision was understood anytime you cast int to float and this question was uint64 specific.
Doug T.
A: 

Safe? What do you mean by safe? As far as the precision is concerned, IEEE-754 float has a 23-(+1)bit mantissa. By forcefully converting a 64-bit value into a "rounded" 24 bit value, you'll inflict a massive loss of precision in the wide range of least-significant bits. Is this loss acceptable in your application? Frankly, if your original value really makes use of the 64-bit range, forcing it into something as small as float doesn't sound as a good idea to me.

AndreyT
+2  A: 

You might try performing your arithmetic in a long double or double first:

typedef long double real_type
real_type x = static_cast<real_type>(long1);
real_type y = static_cast<real_type>(long2);

real_type z = x / y;
float result = static_cast<float>(real_type);
GMan
+1  A: 

Rule of thumb: int can be cast to and back from double

It is safe to cast to and back from float but you will be limited to rather small numbers, about 16 million, and if you exceed the allowed magnitude you will silently lose lower-order precision. With double, you can use much larger integers.

Assuming an IEEE 754 underlying floating point system, you will be able to accurately cast integers of 23 bits to and from float and 52 bits to and from double. Actually, you get one more bit because of the hidden bit, so you can fit an integer up to and including 1FFFFFFFFFFFFF or 9007199254740991 in a double.

So every single 32-bit integer has an exact representation in double; it can be cast to and back safely, and the ordinary arithmetic operations on them will produce exact results.

Indeed, this is what JavaScript does for every integer numeric operation. People who say "floating point is inaccurate" are drastically oversimplifying the matter.

DigitalRoss
Not quite sure what you mean by "to and from double", but in both C and C++ it's only "safe" to cast to int from double if the double is in range. Casting a double >= INT_MAX+1 to int is undefined behaviour. Of course if the double is the result of a cast from int then this condition is satisfied (um. I think), so yes you can cast an int "to and from double", but you can't necessarily cast a double to int, and you can't necessarily cast an int to double, add 1 to it, then cast it back.
Steve Jessop
Sure. I try to cover the important things in answers, but its always hard to know just how far to go into the details...I guess the whole problem would have been solved if I had just worded it "to and back from". Thanks, I may edit...
DigitalRoss
@Steve: To be precise, converting an exceedingly large floating-point value to integral type is *undefined behavior*, not *implementation-defined behavior*
AndreyT
@AndreyT: thanks, I looked it up and must have replaced my comment while you were reading/typing.
Steve Jessop