I would like to manipulate the bitwise representation of floating-point numbers in C#. BinaryWriter and BinaryReader do it this way:
public virtual unsafe void W
Are you trying to avoid unsafe code altogether, or do you just want an alternative to those specific methods on BinaryReader
and BinaryWriter
?
You could use BitConverter.DoubleToInt64Bits and BitConverter.Int64BitsToDouble, which are designed to do exactly what you need, although I think they use the same unsafe conversion behind-the-scenes as the BinaryReader
/BinaryWriter
methods.
You can use byte[] BitConverter.GetBytes(double)
and long BitConverter.ToInt64(byte[],int)
(passing 0 as the start-index), but internally IIRC these use unsafe code, plus have the overhead of an array. Pick your poison...
Another way is to use a custom struct with explicit layout that defines both a long
and a double
at offset 0. This is equivalent to a union
in C.
Something like this:
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Explicit)]
struct DoubleLongUnion
{
[FieldOffset(0)]
public long Long;
[FieldOffset(0)]
public double Double;
}
Then use this:
var union = new DoubleLongUnion();
union.Double = 1.234d;
var longBytes = union.Long;
This will avoid any unsafe code and should perform pretty fast too as you perform the conversion on the stack.
I haven't tried/compiled this but I reckon it should work :)
EDIT
I just tried this and it works. The value of longBytes
above is 4608236261112822104.
Some other values:
0d -> 0L
double.NaN -> -2251799813685248L
double.MinValue -> -4503599627370497L
double.MaxValue -> 9218868437227405311L
Here's a method that does what you want:
public static long DoubleToLong(double d)
{
return new DoubleLongUnion { Double = d }.Long;
}