Ten kod jest niepoprawny.
Zakładając zwyczajowe zasady 2's-dopełnienie bitowe XOR dla podpisanych liczb całkowitych, a następnie
(s^a) < 0
jest w przypadku, gdy s
i a
mają swoje bity znak ustawiony na wartości przeciwne. Zatem
((s^a) < 0 && (s^b) < 0)
wskazuje s
ma podpisać różni się od obu a
i b
, który musi mieć znak równości (udając 0 jest dodatnia). Jeśli dodałeś dwie liczby całkowite równego znaku i otrzymałeś wynik z innego znaku, to musiało nastąpić przepełnienie, więc jest to sprawdzanie przepełnienia.
Jeśli przyjmiemy, że podpisane przepełnienie opakowaniach, to s
ma przeciwny znak od a
i b
dokładnie, gdy wystąpiło przepełnienie. Jednak podpisane przepełnienie jest niezdefiniowanym zachowaniem. Obliczanie s
jest już błędne; musimy sprawdzić, czy wystąpi przepełnienie bez faktycznego wykonywania operacji.
Python nie powinien tego robić. Można zobaczyć, co to ma do zrobienia w Python 2 source code for int.__add__
:
/* casts in the line below avoid undefined behaviour on overflow */
x = (long)((unsigned long)a + b);
if ((x^a) >= 0 || (x^b) >= 0)
To ma oddanych do unsigned aby zdefiniowane zachowanie przepełnienia. Odrzucona do niepodpisanej poprawka została wprowadzona w 5 różnych miejscach w wyniku issue 7406 na śledzenie błędów Pythona, ale wygląda na to, że przegapili miejsce, lub być może zmieniono od tego czasu INPLACE_ADD
. Zostawiłem wiadomość w trackerze.
Co masz na myśli przez "podpisane przepełnienie to niezdefiniowane zachowanie"? – satoru
@satoru: Jakiej części nie rozumiesz? Podpisane przepełnienie lub niezdefiniowane zachowanie? Wypisane przepełnienie występuje, gdy wykonujesz operację na podpisanym sygnale i przepełniasz. Niezdefiniowane zachowanie polega na tym, że standard C pozwala implementacji robić cokolwiek, aż do [wciągania demonów przez nos (włącznie) (http: //www.catb.org/jargon/html/N/nosal-demons.html). – user2357112
Dodałem link do pliku, z którego znalazłem ten fragment. – satoru