2011-12-03 29 views
5

Chỉ cần làm rõ điều này là không một câu hỏi bài tập về nhà như tôi đã nhìn thấy những cáo buộc tương tự nhắm vào các câu hỏi chút-hackish khác:Có thể thực hiện Bit-5 Log2 (Int 32) Bit trong Java?

Điều đó nói rằng, tôi có chút này hack trong C:

#include <stdio.h> 

const int __FLOAT_WORD_ORDER = 0; 
const int __LITTLE_END = 0; 

// Finds log-base 2 of 32-bit integer 
int log2hack(int v) 
{ 
    union { unsigned int u[2]; double d; } t; // temp 
    t.u[0]=0; 
    t.u[1]=0; 
    t.d=0.0; 

    t.u[__FLOAT_WORD_ORDER==__LITTLE_END] = 0x43300000; 
    t.u[__FLOAT_WORD_ORDER!=__LITTLE_END] = v; 
    t.d -= 4503599627370496.0; 
    return (t.u[__FLOAT_WORD_ORDER==__LITTLE_END] >> 20) - 0x3FF; 
} 

int main() 
{ 
    int i = 25; //Log2n(25) = 4 
    int j = 33; //Log2n(33) = 5 

    printf("Log2n(25)=%i!\n", 
     log2hack(25)); 
    printf("Log2n(33)=%i!\n", 
     log2hack(33)); 

    return 0; 
} 

Tôi muốn để chuyển đổi sang Java. Cho đến nay những gì tôi có là:

public int log2Hack(int n) 
    { 
     int r; // result of log_2(v) goes here 
     int[] u = new int [2]; 
     double d = 0.0; 
     if (BitonicSorterForArbitraryN.__FLOAT_WORD_ORDER== 
       BitonicSorterForArbitraryN.LITTLE_ENDIAN) 
     { 
      u[1] = 0x43300000; 
      u[0] = n; 
     } 
     else  
     { 
      u[0] = 0x43300000; 
      u[1] = n; 
     } 
     d -= 4503599627370496.0; 
     if (BitonicSorterForArbitraryN.__FLOAT_WORD_ORDER== 
       BitonicSorterForArbitraryN.LITTLE_ENDIAN) 
      r = (u[1] >> 20) - 0x3FF; 
     else 
      r = (u[0] >> 20) - 0x3FF; 

     return r; 
    } 

(Lưu ý nó bên trong một lớp phân loại bitonic của tôi ...)

Nhưng dù sao, khi tôi chạy này cho cùng một giá trị 33 và 25, tôi nhận được 52 trong mỗi trường hợp.

Tôi biết số nguyên của Java được ký, vì vậy tôi khá chắc chắn rằng có điều gì đó liên quan đến lý do tại sao điều này không thành công. Có ai có bất kỳ ý tưởng làm thế nào tôi có thể nhận được 5-op, 32-bit số nguyên log 2 để làm việc trong Java?

P.S. Đối với hồ sơ, kỹ thuật này không phải của tôi, tôi mượn nó từ đây: http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogIEEE64Float

+2

Chỉnh sửa: Số nguyên của Java được ký. Như một vấn đề của thực tế, mọi kiểu dữ liệu số nguyên thủy ngoại trừ 'char' được ký. –

+0

Sử dụng '>>>' cho phép dịch hợp lý không lặp lại dấu. – fuz

+0

Xin lỗi Sanjay đó là điều tôi muốn nói (rằng họ đã ký) .... Tôi đang thay đổi văn bản ... –

Trả lời

5

Nếu bạn đang sử dụng Java, bạn không thể chỉ cần thực hiện 31 - Integer(v).numberOfLeadingZeros()? Nếu họ thực hiện điều này bằng cách sử dụng __builtin_clz nó sẽ được nhanh chóng.

+0

Đẹp !! Ý tưởng tuyệt vời, tôi đã không đọc về tính năng đó ... Tôi về cơ bản tự dạy Java, đã đọc tài liệu mới bắt đầu của Oracle, v.v. nhưng vẫn không biết một số điều. –

0

Tôi nghĩ bạn không hiểu ý nghĩa của mã đó. Mã C sử dụng liên kết - cấu trúc ánh xạ cùng một bộ nhớ cho hai hoặc nhiều trường khác nhau. Điều đó làm cho nó có thể truy cập vào lưu trữ được phân bổ cho các đôi như số nguyên. Trong mã Java của bạn, bạn không sử dụng một công đoàn mà là hai biến khác nhau được ánh xạ tới các phần khác nhau của bộ nhớ. Điều này làm cho hack không thành công.

Vì Java không có công đoàn, bạn phải sử dụng tuần tự hóa để có được kết quả mong muốn. Vì đó là khá chậm, tại sao không sử dụng một phương pháp khác để tính logarit?

+0

Bất kỳ đề xuất nào khác ngoài bảng tra cứu để thay thế op thấp hơn chỉ đơn giản là bit dịch chuyển giá trị của tôi sửa chữa rõ ràng và dễ dàng)? –

+0

@Jason Trên trang bạn đã liên kết, có một số cách tiếp cận khác mà người dùng có thể xem xét sử dụng. Nhưng, vấn đề với cách tiếp cận bảng tra cứu trên trang mà bạn đã liên kết là gì? – fuz

+0

Phương pháp duy nhất khác được liệt kê là một phương pháp dựa trên chuyển dịch mà trong khi hơi nhanh hơn so với phương pháp truyền thống chậm hơn nhiều so với các phương pháp hack bit khác, bao gồm cả bảng. Bảng tra cứu không sao (7 ops cho 32 bit), nhưng tôi đã tự hỏi liệu có ai đã nhìn thấy bất kỳ hack Java log2 mới nhanh hơn nào không, ví dụ: giống như 5 op khác ... –

0

Bạn đang sử dụng công đoàn để chuyển đổi cặp int của bạn thành một đôi với cùng một mẫu bit. Trong Java, bạn có thể làm điều đó với Double.longBitsToDouble, và sau đó chuyển đổi trở lại với Double.doubleToLongBits. Java luôn luôn (hoặc ít nhất là tạo ấn tượng luôn luôn là người lớn), vì vậy bạn không cần kiểm tra độ tin cậy.

Điều đó nói rằng, nỗ lực của tôi để điều chỉnh mã của bạn thành Java không hoạt động. Việc ký kết các số nguyên Java có thể là một vấn đề.

Các vấn đề liên quan