Chỉ có thể tràn khi cả hai con số có cùng một dấu. Nếu cả hai đều dương, thì bạn có tràn nếu toán học A + B > LLONG_MAX
hoặc tương đương B > LLONG_MAX - A
. Vì phía bên phải là không âm, điều kiện sau đã ngụ ý B > 0
. Các đối số tương tự cho thấy rằng đối với trường hợp tiêu cực, chúng tôi cũng không cần phải kiểm tra các dấu hiệu của B
(nhờ Ben Voigt cho chỉ ra rằng kiểm tra dấu hiệu trên B
là không cần thiết). Sau đó, bạn có thể kiểm tra
if (A > 0) {
return B > (LLONG_MAX - A);
}
if (A < 0) {
return B < (LLONG_MIN - A);
}
return false;
để phát hiện tràn. Các tính toán này không thể tràn do kiểm tra ban đầu.
Kiểm tra ký hiệu của kết quả là A + B
sẽ hoạt động với ngữ nghĩa quấn quanh được bảo đảm của tính toán số nguyên tràn. Nhưng tràn các số nguyên đã ký là hành vi không xác định, và thậm chí trên các CPU nơi xung quanh là hành vi được thực hiện, trình biên dịch có thể giả định rằng không có hành vi không xác định nào xảy ra và loại bỏ hoàn toàn kiểm tra tràn khi thực hiện như vậy. Vì vậy, kiểm tra đề xuất trong các ý kiến cho câu hỏi là rất không đáng tin cậy.
Nguồn
2013-04-10 08:31:57
'nếu ((A <0 && B <0 && A+B> 0) || (A> 0 && B> 0 && A + B <0)) {/ * Overflow * /} 'Bạn chỉ có thể tràn nếu cả A và B có cùng dấu.Nếu họ làm, và A + B không có dấu hiệu giống nhau, thì bạn có vấn đề tràn. Trong các tin tức khác, đây là phương pháp cơ bản nhanh nhất xung quanh, vì nó thực hiện trong thời gian không đổi, và chỉ thực hiện việc bổ sung một lần. – FrankieTheKneeMan
Bạn nên đăng nó như một câu trả lời. Nhân tiện, có một trường hợp góc khi 'A = B = 0x8000000000000000', sau đó 'A + B = 0' và mã của bạn không hoạt động: p – riv
@FrankieTheKneeMan Lỗi tràn là hành vi không xác định. – john