How to get the bits of a “double” as a “long”

后端 未结 3 1530
太阳男子
太阳男子 2021-02-20 04:58

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         


        
相关标签:
3条回答
  • 2021-02-20 05:26

    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.

    0 讨论(0)
  • 2021-02-20 05:32

    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...

    0 讨论(0)
  • 2021-02-20 05:48

    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;
    }
    
    0 讨论(0)
提交回复
热议问题