Jakie jest użycie 1ll w instrukcji long long l = (int) a * 1ll * (int) b; w C / C ++?


Najlepsza odpowiedź

Po pierwsze, uwaga: C i C ++ to dwa różne języki. Poniższa odpowiedź dotyczy obu, ale czasami odpowiedź różni się w zależności od języka. W obu językach wyrażenie c/c++ ma niezdefiniowane zachowanie.

To jest głupi sposób na promocję typu. Zwróć uwagę, że przykład w szczegółach jest sformułowany jaśniej:

int a, b;

long long l = a * 1ll * b;

Jak zauważa OP, 1ll deklaruje long long literał liczby całkowitej.

Jego obecność w kodzie promuje całe mnożenie do long long poprzez zwykłe konwersje arytmetyczne, w szczególności promocje w postaci liczb całkowitych.

Wyrażenie jest analizowane jako ((a * 1ll) * b). Pierwsze mnożenie po prostu zwraca wartość a jako long long. Drugie mnożenie zostanie następnie zaktualizowane do long long.

Możesz uzyskać ten sam efekt z wyraźnym rzutowaniem:

int a, b;

long long l = (long long)a * b;

To trochę więcej pisania, ale tylko trochę. Drugie sformułowanie jest z pewnością jaśniejsze, przynajmniej dla mnie.

Możesz też zrobić coś takiego:

long long l = a;

l *= b;

Ale to znowu zaczyna być głupie.

Dlaczego musisz promować? Jeśli masz wystarczająco duże wartości, mnożenie może się przepełnić. Promując do long long, gwarantujesz, że tak się nie stanie.

Załóżmy, że 32-bitowe int i 64- bit long long i uzupełnienie do 2. Największy produkt, jaki możesz uzyskać, to -2 ^ {31} \ times -2 ^ {31} = 2 ^ {62}. To poniżej największej dodatniej wartości, jaką możesz przedstawić, 2 ^ {63} – 1, więc masz gwarancję, że nie przepełnisz.

Odpowiedź

a i b to int int * int -> int (wszystko w zakresie 32-bitowym int tj. -2147483648 int 2147483647) . „. 2147483647 * 2 = -2 a nie 4294967294 operator przypisania ma asocjację od prawej do lewej , tj. W wyrażeniu: long long l = a * b; a * b jest obliczane jako pierwsze int * int-> int, jeśli a = 2147483647 i b = 2 a * b -> – 2 a nie 4294967294 teraz l = -2 -2 jest konwertowane na long long i przechowywane w l

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *