2008-10-06 16 views
11

1. Làm cách nào tôi có thể diễn giải lại một phao lên một int (hoặc gấp đôi thành một khoảng thời gian dài)?Làm cách nào để diễn giải lại việc truyền phao sang int? Có toán tử chuyển đổi không tĩnh hoặc toán tử gán do người dùng xác định cho chuyển đổi trên 'this' không?

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

Tôi chỉ muốn sao chép mẫu bit từ f thành i. Điều này có thể giải quyết như thế nào?

2. Các nhà khai thác ngầm và rõ ràng trong C# sử dụng một đối tượng trung gian bởi vì các chức năng điều hành là tĩnh

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

Điều này là tốt với nhiều loại tài liệu tham khảo, nhưng đối với giá trị các loại mà là lớn (nói 20- 30 byte), điều này sẽ gây ra sao chép dữ liệu không cần thiết. Tôi hiểu có đúng không? Và nếu có, thì tại sao C# không có toán tử chuyển đổi không tĩnh hoặc toán tử gán do người dùng định nghĩa để chuyển đổi/chuyển nhượng diễn ra trên 'this'? Nếu có, làm cách nào để làm điều đó?

+4

Trong tương lai xin vui lòng gửi hai câu hỏi riêng biệt. –

+4

và không viết tất cả văn bản trong dòng tiêu đề. – shoosh

Trả lời

8
  1. Lớp BitConverter có thể truy xuất byte cho bất kỳ loại nguyên thủy nào mà bạn có thể sử dụng để tạo int. Một tùy chọn khác là Buffer.BlockCopy nếu bạn có số lượng lớn chuyển đổi để thực hiện.

    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. Không không có lựa chọn nào khác được đưa ra trong C#, tuy nhiên, tôi nghĩ rằng trong khi bạn đang đúng theo nghĩa là sẽ có một bản sao được thực hiện, bất cứ thực hiện đầy đủ đơn giản sẽ JIT tối ưu hóa thực hiện, có thể loại bỏ sự cần thiết cho một bản sao.

+0

Nó không rõ ràng rằng làm cho các nhà điều hành một nhà điều hành dụ sẽ loại bỏ sự cần thiết cho các bản sao anyway. Câu hỏi có vẻ hơi bối rối với tôi. –

+0

Quay lại '08 Tôi đã đưa ra các giả định rằng JIT sẽ hoạt động tương tự như trình biên dịch C++ w.r.t. phương pháp thành viên, nhưng tôi chưa thấy nó hoạt động như thế trong thực tế. – user7116

8

1: BitConverter (dưới dạng bản sao biến đổi) là một tùy chọn; là mã không an toàn (không cần bộ đệm trung gian):

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: lưu ý rằng bạn nên hạn chế kích thước của cấu trúc. Tôi không thể tìm thấy một trích dẫn fr nó, nhưng số "16 byte" (tối đa, như là một đề nghị) dường như dính trong tâm trí của tôi. Trên đây, hãy xem xét một loại tham chiếu bất biến (lớp).

8

Trừ mã không an toàn - đây là phương pháp nhanh nhất tôi biết để thực hiện một diễn giải:

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

Hope this helps một ai đó.

1

Phương pháp này tuy không an toàn, hoạt động như một giải pháp chung

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); 
} 
Các vấn đề liên quan