Wednesday, February 9, 2011

Two C# questions; how can I reinterpret cast a float to an int? Does C# have a non-static conversion operator or user-defined assignment operator so that the conversion takes place on 'this'?

1. How can I reinterpret cast a float to a int (or a double to a long)?

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

I only want to copy the bit-pattern from f to i. How can this be done?

2. The implicit and explicit operators in C# uses one intermediate object because the operator function is 'static'

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

This is fine for reference types, but for value-types which are big (say 20-30 bytes), this will cause unnecessary data copy. Is my understanding correct? And If yes, then why doesn't C# have a non-static conversion operator or user-defined assignment operator so that the conversion/assignment takes place on 'this'? If it does, whats the way to do it?

Thanks

    1. The BitConverter class can retrieve the bytes for any primitive type, which you can then use to create an int. Another option is Buffer.BlockCopy if you have large amounts of converting to do.

      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. No there is no other option given in C#, however, I think that while you're correct in the sense that there will be a copy made, any sufficiently simple implementation will have JIT optimizations done, possibly removing the need for a copy.

  • 1: BitConverter (as sixlettervariables) is an option; as is unsafe code (which doesn't need an intermediate buffer):

        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: note that you should limit the size of structs. I can't find a citation fr it, but the number "16 bytes" (max, as a recommendation) seems to stick in my mind. Above this, consider an immutable reference-type (class).

0 comments:

Post a Comment