2012-10-26 25 views
10

khi tôi đọc mã nguồn của phiên bản java 1.7.0_09, tôi thấy rằng việc thực hiện phương thức toString của lớp Integer sử dụng int âm để tính toán mod hoạt động, có ý nghĩa gì không? mã như sau:tại sao sử dụng int âm cho hoạt động mod trong phương thức toString của lớp Integer trong java src

public static String toString(int i, int radix) { 

    if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) 
     radix = 10; 

    /* Use the faster version */ 
    if (radix == 10) { 
     return toString(i); 
    } 

    char buf[] = new char[33]; 
    boolean negative = (i < 0); 
    int charPos = 32; 

    if (!negative) {  
     i = -i;    //***** change i to negative 
    } 

    while (i <= -radix) { 
     buf[charPos--] = digits[-(i % radix)]; //***** change back to positive after 
               //***** mod operation 
     i = i/radix; 
    } 
    buf[charPos] = digits[-i]; 

    if (negative) { 
     buf[--charPos] = '-'; 
    } 

    return new String(buf, charPos, (33 - charPos)); 
} 

Trả lời

10

Theo thuật toán, bạn cần một dòng (< radix) số nguyên không âm nhỏ sẽ lấp đầy bộ đệm ký tự với chữ số từ phải sang trái. Tiêu chuẩn, trường tiểu học cách để làm cho công việc này là đặt một dấu hiệu ở đầu số, và sau đó in giá trị tuyệt đối của số.

Nhưng hãy tưởng tượng nếu các quy tắc đã có i luôn luôn là tích cực trong vòng lặp rằng:

if (negative) { 
    i = -i; // change i to positive 
} 

Nếu i sẽ xảy ra là Integer.MIN_VALUE, sau đó -i cũng sẽ xảy ra là Integer.MIN_VALUE. Two's complement biến số nguyên có thể lưu trữ exactly one more negative integer than they can store positive integers. Tuy nhiên, nếu bất biến thay vào đó, i luôn là giá trị tuyệt đối của âm, giá trị này sẽ luôn phù hợp với một số int.

Tại sao không chỉ sử dụng Math.abs() hoặc khối if? Đương nhiên, các số nguyên được chuyển đổi thành chuỗi rất thường xuyên trong nhiều chương trình máy tính, vì vậy rất hữu ích để giữ cho toString càng nhanh càng tốt. Vấn đề là, cả hai câu lệnh Math.abs()if có thể sẽ được biên dịch để sử dụng các hướng dẫn chi nhánh khi được biên dịch thành mã máy. Branches có xu hướng can thiệp với instruction pipelining; do đó, khi chú ý đến hiệu suất, bạn có thể chọn xóa các câu lệnh if khỏi vòng lặp khi có thể.

LƯU Ý: Loại tối ưu hóa này hiếm khi là ý tưởng hay! Hiệu năng đạt được là rất nhỏ trừ khi mã của bạn được gọi rất thường xuyên (như mã này) hoặc bạn đang xây dựng một thư viện với nhiều người dùng và vài người đọc/sửa đổi (như mã này), và làm cho mã khó đọc, dễ hiểu hơn thay đổi. Bằng cách thực hiện tối ưu hóa này, các kỹ sư Java có thể tăng tốc mã của bạn rất ít - nhưng nếu bạn đặt các kỹ thuật như thế này vào mã bạn viết, đồng nghiệp/học sinh của bạn có thể không có xu hướng hỏi Stack Overflow tại sao mã của bạn khó hiểu. :)

TL; DR: Chỉ là một phỏng đoán được giáo dục, nhưng đây là sự kết hợp giữa toán học bổ sung và tối ưu hóa mã hai.

+0

Thx rất nhiều! Tôi nghĩ rằng đây là những gì tôi muốn! – Judking

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