I need to save UInt32, Int32 and float values inside a variable. Can I use double
without losing information (e.g. losing some digits in the conversion) or do I need to use a arbitrary precision class?
From my current research it seems I can, as I can store the maximum value of UInt32 without loosing information:
Assert.AreEqual(UInt32.MaxValue, Convert.ToUInt32(Convert.ToDouble(UInt32.MaxValue)));
Is there anything I missed?
Being able to store the maximum value of UInt32
without losing information doesn't necessarily mean you'll be able to store all values in UInt32
without losing information - after all, there are plenty of long
values which can be stored in a double
even though some smaller values can't. (262 can easily be stored exactly in a double
, but 262 - 1 can't, for example.)
However, you are okay - the mantissa for double
is 52-bits long, so any integer with fewer than 52 bits can trivially be stored as value * 20 (i.e. an effective scale of 0).
And yes, float
values can be converted to double
with no loss of precision too.
However, note that this doesn't mean that 0.1f == 0.1d
for example - it just means that (double) 0.1f
is exactly the same number as 0.1f
, in a different representation.
It's also worth noting that Int32
doesn't have a smaller range than UInt32
- they both have a range of exactly 232 consecutive values. However, Int32
does have a smaller "absolute" value, and with the way that sign is represented in floating point values, that's relevant. You still actually need 32 bits in order to store the absolute value of every Int32
, because Int32.MinValue
is -10000...0000 in binary (32 bits in total), or -(231 + 1).
Finally, float
isn't just double
with less precision - it's got a smaller range too. It only has 8 bits for the exponent compared with 11 in double
. So there are numbers well within the range of double
which are outside the range of float
, even if they don't have many significant (binary) digits.
See more on this question at Stackoverflow