Jaké je použití 1ll ve výpisu long long l = (int) a * 1ll * (int) b; v C / C ++?


Nejlepší odpověď

Za prvé, gripe: C a C ++ jsou dva různé jazyky. Níže uvedená odpověď platí pro oba, ale někdy se odpověď v různých jazycích liší. A v obou jazycích má výraz c/c++ nedefinované chování.

Toto je praštěný způsob, jak získat typovou propagaci. Příklad v detailech je formulován jasněji:

int a, b;

long long l = a * 1ll * b;

Jak OP uvádí, 1ll deklaruje celočíselný literál long long.

Jeho přítomnost zde v kódu podporuje celé násobení na long long prostřednictvím obvyklých aritmetických převodů, zejména celočíselné propagace.

Výraz se analyzuje jako ((a * 1ll) * b). První násobení pouze vrátí hodnotu a jako long long. Druhá multiplikace se poté upgraduje také na long long.

Stejného efektu jste mohli dosáhnout s explicitním obsazením:

int a, b;

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

Je to trochu více psaní, ale jen mírně. Druhá formulace je určitě jasnější, alespoň pro mě.

Můžete také udělat něco jako:

long long l = a;

l *= b;

Ale to už zase začíná být hloupé.

Pokud jde o to, proč musíte propagovat? Pokud máte dostatečně velké hodnoty, mohlo by dojít k přetečení násobení. Propagací na long long zaručujete, že ne.

Předpokládejme 32bitové int a 64- bit long long a reprezentace doplňku 2. Největší produkt, který můžete získat, je -2 ^ {31} \ krát -2 ^ {31} = 2 ^ {62}. To je pod největší kladnou hodnotou, kterou můžete představovat, 2 ^ {63} – 1, takže máte zaručeno, že nepřeteknete.

Odpověď

a a b jsou int int * int -> int (vše v rozsahu 32 bitů int tj. -2147483648 int 2147483647) . „. 2147483647 * 2 = -2 a ne 4294967294 operátor přiřazení má asociativitu zprava doleva tj. Ve výrazu: long long l = a * b; a * b se vypočítá nejprve int * int-> int, pokud a = 2147483647 a b = 2 a * b -> – 2 a ne 4294967294 nyní l = -2-2 se převede na long long a uloží se do l

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *