如何将"双"的位称为"长"

Qwe*_*tie 10 .net floating-point bit-manipulation

我想在C#中操纵浮点数的按位表示.BinaryWriter和BinaryReader这样做:

public virtual unsafe void Write(double value)
{
    ulong num = *((ulong*) &value);
    ...
}
public virtual unsafe double ReadDouble()
{
    ...
    ulong num3 = ...;
    return *((double*) &num3);
}
Run Code Online (Sandbox Code Playgroud)

有没有办法在没有不安全代码的情况下执行此操作,并且没有实际使用BinaryWriter和BinaryReader的开销?

Dre*_*kes 8

另一种方法是使用具有显式布局的自定义结构,该结构定义a long和a double偏移0.这相当于unionC中的a .

像这样的东西:

using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Explicit)]
struct DoubleLongUnion
{
    [FieldOffset(0)] 
    public long Long;
    [FieldOffset(0)] 
    public double Double;
}
Run Code Online (Sandbox Code Playgroud)

然后用这个:

var union = new DoubleLongUnion();
union.Double = 1.234d;
var longBytes = union.Long;
Run Code Online (Sandbox Code Playgroud)

这将避免任何不安全的代码,并且当您在堆栈上执行转换时也应该执行得非常快.

我没有尝试/编译这个,但我认为它应该工作:)

编辑

我刚试过这个并且它有效.以上值longBytes是4608236261112822104.

其他一些价值观:

0d              -> 0L
double.NaN      -> -2251799813685248L
double.MinValue -> -4503599627370497L
double.MaxValue -> 9218868437227405311L
Run Code Online (Sandbox Code Playgroud)

这是一个做你想要的方法:

public static long DoubleToLong(double d)
{
    return new DoubleLongUnion { Double = d }.Long;
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*ell 6

你可以使用byte[] BitConverter.GetBytes(double)long BitConverter.ToInt64(byte[],int)(传递0作为起始索引),但在内部 IIRC这些使用不安全的代码,加上数组的开销.选择你的毒药......


Luk*_*keH 6

你们是不是要完全避免不安全的代码,或者你只是想在这些具体方法的替代BinaryReaderBinaryWriter

您可以使用BitConverter.DoubleToInt64Bitsand BitConverter.Int64BitsToDouble,它们旨在完全满足您的需要,尽管我认为它们在幕后使用与BinaryReader/BinaryWriter方法相同的不安全转换。