如何将浮点数重新解释为整数?是否有非静态转换运算符或用户定义的赋值运算符用于在"this"上进行转换?



1。如何重新解释将float转换为int(或将double转换为long)?

float f = 2.0f;
int i = (int)f; // causes conversion

我只想把比特模式从f复制到i。如何做到这一点?

2。C#中的隐式和显式运算符使用一个中间对象,因为运算符函数是静态

public static implicit operator MyClass(double s)
{
    return new MyClass(s);
} 
..
..
MyClass m = 2.2; // this code uses 'm' and one intermediate object.

这对于引用类型来说很好,但对于较大的值类型(比如20-30字节),这将导致不必要的数据复制。我的理解正确吗?如果是,那么为什么C#没有一个非静态的转换运算符或用户定义的赋值运算符,以便在"this"上进行转换/赋值?如果是这样,怎么办?

1:BitConverter(作为六个字母的变量)是一个选项;不安全代码也是如此(不需要中间缓冲区):

    float f = 2.0f;
    int i;
    // perform unsafe cast (preserving raw binary)
    unsafe
    {
        float* fRef = &f;
        i = *((int*)fRef);
    }
    Console.WriteLine(i);
    // prove same answer long-hand
    byte[] raw = BitConverter.GetBytes(f);
    int j = BitConverter.ToInt32(raw, 0);        
    Console.WriteLine(j);

2:注意你应该限制structs的大小。我找不到它的引文,但数字"16字节"(最大值,作为建议)似乎一直萦绕在我的脑海中。在此之上,考虑一个不可变的引用类型(类)。

禁止不安全的代码-这是我所知道的执行重新解释的最快方法:

    [StructLayout(LayoutKind.Explicit)]
    private struct IntFloat
    {
        [FieldOffset(0)]
        public int IntValue;
        [FieldOffset(0)]
        public float FloatValue;
    }
    private static float Foo(float x)
    {
        var intFloat = new IntFloat { FloatValue = x };
        var floatAsInt = intFloat.IntValue;
        ...

希望这能帮助到别人。

  1. BitConverter类可以检索任何基元类型的字节,然后可以使用这些基元创建int。如果要进行大量转换,另一个选项是Buffer.BlockCopy。

    float ff = 2.0f;
    int ii = BitConverter.ToInt32(BitConverter.GetBytes(ff), 0);
    float[] ff = new float[...];
    int[] ii = new int[ff.Length];
    Buffer.BlockCopy(ff, 0, ii, 0, ff.Length * 4); // byte-wise copy of ff into ii
    
  2. 不,在C#中没有给出其他选项,但是,我认为,虽然您在将要创建副本的意义上是正确的,但任何足够简单的实现都将进行JIT优化,可能会消除对副本的需要。

这种方法虽然不安全,但可以作为通用解决方案

static unsafe TDest ReinterpretCast<TSource, TDest>(TSource source)
{
    var tr = __makeref(source);
    TDest w = default(TDest);
    var trw = __makeref(w);
    *((IntPtr*)&trw) = *((IntPtr*)&tr);
    return __refvalue(trw, TDest);
}

这应该是最快、最干净的方法:

public static class ReinterpretCastExtensions {
   public static unsafe float AsFloat( this int n ) => *(float*)&n;
   public static unsafe int AsInt( this float n ) => *(int*)&n;
}
public static class MainClass {
   public static void Main( string[] args ) {
      Console.WriteLine( 1.0f.AsInt() );
      Console.WriteLine( 1.AsFloat() );
   }
}