8

Nhìn vào lắp ráp x86 do trình biên dịch tạo ra, tôi nhận thấy rằng các bộ phận số nguyên (chưa ký) đôi khi được thực hiện dưới dạng số nguyên. Những tối ưu hóa dường như theo các hình thứcThực hiện phép chia số nguyên sử dụng phép nhân

value/n => (value * ((0xFFFFFFFF/n) + 1))/0x100000000 

Ví dụ, biểu diễn một bộ phận của 9:

12345678/9 = (12345678 * 0x1C71C71D)/0x100000000 

Một bộ phận của 3 sẽ sử dụng phép nhân với 0x55555555 + 1, và vân vân.

Khai thác thực tế là lệnh mul lưu trữ phần cao của kết quả trong thanh ghi edx, kết quả cuối cùng của bộ phận có thể thu được bằng cách sử dụng phép nhân đơn với giá trị phép thuật. (Mặc dù tối ưu hóa này đôi khi được sử dụng kết hợp với một chút thay đổi khôn ngoan ở cuối.)

Tôi muốn có một số thông tin chi tiết về cách thức này thực sự hoạt động. Cách tiếp cận này hợp lệ khi nào? Tại sao phải 1 được thêm vào "số ma thuật" của chúng tôi?

+2

Hằng số mà bạn nhân với là xấp xỉ của nghịch đảo. Các ngẫu nhiên +/- 1 ở đây và có để đảm bảo rằng nó luôn luôn "làm tròn" một cách chính xác. Chứng minh rằng một phương pháp cụ thể là chính xác có thể được thực hiện bằng toán học, hoặc bằng cách kiểm tra sức mạnh vũ phu của tất cả các tử số. (Đối với 32-bit, điều này là hoàn toàn khả thi.) – Mysticial

+0

@Mysticial: Điều đó trông giống như một câu trả lời cho tôi. –

+0

@ScottHunter Có thể sau này khi tôi nghỉ việc. Tôi không có các công cụ ở đây để đưa ra một câu trả lời toàn diện. – Mysticial

Trả lời

10

Phương pháp đó được gọi là "Phân chia theo phép nhân bất biến".

Hằng số mà bạn đang xem thực sự xấp xỉ đối ứng.

Vì vậy, chứ không phải là tính toán:

N/D = Q 

bạn làm điều gì đó giống như thay vì điều này:

N * (1/D) = Q 

nơi 1/D là một đối ứng có thể được precomputed.

Về cơ bản, các số nghịch đảo không chính xác trừ khi D là nguồn cấp hai. Vì vậy, sẽ có một số lỗi liên quan đến vòng lặp. Các +1 mà bạn thấy là có để sửa chữa cho các lỗi vòng-off.


Ví dụ phổ biến nhất là phân chia bởi 3:

N/3 = (N * 0xaaaaaaab) >> 33 

đâu 0xaaaaaaab = 2^33/3 + 1.

Cách tiếp cận này sẽ khái quát hóa với các ước tính khác.

+1

Tham chiếu kinh điển là: T. Granlund và PL Montgomery,“ Phân chia bằng các số nguyên bất biến bằng phép nhân, ”trong * Kỷ yếu của Hội thảo SIGPLAN '94 về thiết kế ngôn ngữ lập trình và thực hiện *, 1994, trang 61–72. – njuffa

+1

bổ sung, nhiều tài liệu tham khảo gần đây: N. Möller và T. Granlund, “Cải thiện sự phân chia bởi số nguyên bất biến,” * IEEE giao dịch trên máy tính *, vol. 60, không. 165 -175 2, tr., Tháng Hai 2011. – njuffa

+0

tổng quát của bạn và các giấy tờ chứng minh là sai. Ngoài ra, 0x55555556 để chia cho 3 chỉ hoạt động cho phạm vi đã ký, tức là. lên đến 2^31. – Jester

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