C# 如何重新解释将浮点转换为整数?在'上是否有用于转换的非静态转换运算符或用户定义的赋值运算符;这个';?

C# 如何重新解释将浮点转换为整数?在'上是否有用于转换的非静态转换运算符或用户定义的赋值运算符;这个';?,c#,C#,一,。 如何将浮点转换为int(或double转换为long) 我只想将位模式从f复制到I。如何做到这一点 二,。 C#中的隐式和显式运算符使用一个中间对象,因为运算符函数是静态的 public static implicit operator MyClass(double s) { return new MyClass(s); } .. .. MyClass m = 2.2; // this code uses 'm' and one intermediate object. 这对

一,。 如何将浮点转换为int(或double转换为long)

我只想将位模式从
f
复制到
I
。如何做到这一点

二,。 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”上进行?如果有,怎么做

  • 该类可以检索任何基元类型的字节,然后您可以使用这些字节创建一个int。另一个选项是如果您有大量转换要做

    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
    
  • 不,在C#中没有给出其他选项,但是,我认为,虽然您在复制的意义上是正确的,但是任何足够简单的实现都将完成JIT优化,可能不再需要复制

  • 1:位转换器(作为六个变量)是一个选项;与不安全代码一样(不需要中间缓冲区):


    2:注意,应该限制结构的大小。我找不到它的引文,但数字“16字节”(最大,作为建议)似乎一直留在我的脑海中。在此之上,考虑一个不可变的引用类型(类).< /p> 禁止不安全代码-这是我知道的最快的重新解释的方法:

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

    希望这对某人有所帮助。

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

    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);
    }
    
    静态不安全TDest重新解释广播(TSource-source)
    {
    var tr=uuu makeref(来源);
    TDest w=默认值(TDest);
    var trw=uu makeref(w);
    *((IntPtr*)和trw)=*((IntPtr*)和tr);
    返回参考值(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() );
       }
    }
    

    今后,请发布两个独立的问题。不要在标题中写下所有的文字。可能的重复。不清楚将操作员作为实例操作员是否会消除对副本的需要。这个问题似乎有点让我困惑。回到08,我假设JIT的行为类似于C++编译器W.R.T.成员方法,但我还没有看到它在实践中是这样工作的。
    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() );
       }
    }