2015-06-26 12 views
14

Chức năng C sau đây là từ dự án fastapprox.Tại sao độ lệch số mũ của IEEE-754 được sử dụng trong mã C này là 126.94269504 thay vì 127?

static inline float 
fasterlog2 (float x) 
{ 
    union { float f; uint32_t i; } vx = { x }; 
    float y = vx.i; 
    y *= 1.1920928955078125e-7f; 
    return y - 126.94269504f; 
} 

Một số chuyên gia tại đây có thể giải thích lý do sai lệch số mũ được sử dụng trong mã trên là 126,94269504 thay vì 127? Có giá trị thiên vị chính xác hơn không?

+1

biên dịch cảnh báo từ 'nổi y = vx.i '' có thể mất dữ liệu ". –

+1

Tại sao không hỏi ai đó đã viết nó? Nó không thực sự là một câu hỏi mã hóa, nó là một câu hỏi về thuật toán, đúng không? – Dan

+1

@Dan - Có, nhưng nhà phát triển C là những người có thể đọc mã C và họ thường quan tâm đến kiến ​​thức cấp thấp như vậy. Theo googling của tôi, đã có rất nhiều dự án C sử dụng các hàm được triển khai trong fastapprox, vì vậy có thể câu trả lời cho câu hỏi này cũng hữu ích cho các nhà phát triển C. Một điều nữa để nói, tại sao lại hỏi tác giả cách duy nhất để trả lời câu hỏi? Ở đây, tôi có thể nhận được phản hồi nhanh hơn từ các chuyên gia khác nhau. – Astaroth

Trả lời

9

Trong dự án bạn đã liên kết, chúng bao gồm Mathematica notebook với giải thích thuật toán của chúng, bao gồm giá trị "bí ẩn" -126.94269.
Nếu bạn cần người xem, bạn có thể tải miễn phí từ số Mathematica website.

Chỉnh sửa: Vì tôi cảm thấy hào phóng, đây là phần có liên quan in screenshot form.

Nói một cách đơn giản, chúng giải thích rằng giá trị "đơn giản hơn, nhanh hơn và kém chính xác hơn".
Họ đang không sử dụng -126.94269 ở vị trí của -127, họ đang sử dụng nó ở vị trí của kết quả của việc tính toán sau (giá trị làm tròn cho ngắn gọn):

-124.2255 - 1.498 * mx - (1.72588/(0.35201 + mx)) 
+2

Tôi thích nó khi họ sử dụng các số 1.1920928955078125e-7 và 126.94269504, với giá trị chính xác 17 và 11 chữ số, tương ứng, và sau đó gắn một 'f' ở cuối để làm cho chúng nổi! –

+0

@SteveSummit có 17 chữ số thập phân; có lẽ chúng được thể hiện chính xác trong IEEE754 –

+0

@Mr_Llama, tôi thấy, cảm ơn bạn rất nhiều. Nó chỉ ra rằng tôi đã vội vàng đọc trang web của họ. Tôi đã không nhận thấy có một Notebook Mathematica như vậy. – Astaroth

-4

Vâng, không, 126.94269504 không phải là giá trị thiên vị "chính xác hơn". Mã này đang làm điều gì đó rất, rất lạ; Tôi khá ngạc nhiên khi nó hoạt động. Nó lấy các bit của float như thể chúng là int (theo kinh nghiệm của tôi thường cho bạn giá trị hoàn toàn là rác, nhưng có thể không), sau đó lấy giá trị int "garbage" đó và chuyển nó trở lại float, sau đó thực hiện một số toán trên đó. Đây là, như họ nói, một cách nhanh chóng và gần đúng để làm một cái gì đó, trong trường hợp này, lấy bản ghi cơ sở-2. Nó không có tác dụng gì cả, nhưng sự khác biệt giữa 127 và 126.94269504 rõ ràng chỉ là một trong những yếu tố lừa đảo ngốc nghếch có ý định cứu vãn một số ý nghĩa từ những gì nên là mã vô nghĩa. (Sắp xếp của một "hai gần như sai lầm làm cho một điều gần như đúng".)

Nếu bạn muốn trích xuất chính xác mantissa và số mũ của một phao (mặc dù điều này sẽ không được nhanh hay gần đúng), cách thông thường để thực hiện với chức năng frexpf.

+4

-1; nó không phải là rác nếu bạn dựa vào một mã hóa cụ thể (cụ thể là [IEEE754] (https://en.wikipedia.org/wiki/Single-precision_floating-point_format)), và "một số toán học" nó làm là rất thận trọng. – MooseBoys

+3

Phần số mũ của một số dấu phẩy động là logarit, trong khi phần mantissa là tuyến tính. Mã đơn giản dường như áp dụng một xấp xỉ xấp xỉ tuyến tính tốt nhất, trong đó độ lệch trục y của phương trình tuyến tính được kết hợp với độ lệch số mũ. – njuffa

+2

Nó đồng thời là một kỹ thuật điên rồ và rực rỡ. Như tôi đã nói, tôi rất ngạc nhiên khi nó hoạt động, nhưng tôi đã thử nó, và tôi có thể thấy điều đó. Tôi thậm chí có thể hiểu nó hoạt động như thế nào, nhưng kết quả cuối cùng vẫn để lại cho tôi cảm giác, ồ, được gọi là 'free' hai lần trên cùng một con trỏ và sắp xếp dữ liệu cho tôi, hay cái gì đó! –

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