Trong khi một người signed long long int
sẽ không giữ A*B
, hai trong số họ sẽ. Vì vậy, A*B
có thể được phân tách theo các thuật ngữ cây theo số mũ khác nhau, bất kỳ trong số chúng phù hợp với một signed long long int
.
A1=A>>32;
A0=A & 0xffffffff;
B1=B>>32;
B0=B & 0xffffffff;
AB_0=A0*B0;
AB_1=A0*B1+A1*B0;
AB_2=A1*B1;
Tương tự cho C*D
.
Theo cách thẳng, phép trừ có thể được thực hiện cho mọi cặp AB_i
và CD_i
tương tự, bằng cách sử dụng một bit mang bổ sung (chính xác là số nguyên 1 bit) cho mỗi cặp. Vì vậy, nếu chúng ta nói E = A * BC * D, bạn sẽ nhận được một cái gì đó như:
E_00=AB_0-CD_0
E_01=(AB_0 > CD_0) == (AB_0 - CD_0 < 0) ? 0 : 1 // carry bit if overflow
E_10=AB_1-CD_1
...
Chúng tôi tiếp tục bằng cách chuyển phía trên một nửa số E_10
để E_20
(shift 32 và thêm, sau đó xóa nửa trên của E_10
).
Bây giờ bạn có thể loại bỏ bit carry E_11
bằng cách thêm nó với dấu bên phải (thu được từ phần không mang theo) vào E_20
. Nếu điều này gây ra tràn, kết quả sẽ không phù hợp.
E_10
bây giờ có đủ 'không gian' để lấy nửa trên E_00
(thay đổi, thêm, xóa) và bit mang E_01
.
E_10
bây giờ có thể lớn hơn một lần nữa, vì vậy chúng tôi lặp lại việc chuyển sang E_20
.
Tại thời điểm này, E_20
phải trở thành số không, nếu không kết quả sẽ không phù hợp. Nửa trên E_10
là trống do kết quả của quá trình chuyển.
Bước cuối cùng là chuyển nửa dưới E_20
vào E_10
một lần nữa.
Nếu kỳ vọng E=A*B+C*D
sẽ phù hợp với các khoản signed long long int
giữ, bây giờ chúng ta có
E_20=0
E_10=0
E_00=E