Portál AbcLinuxu, 14. května 2025 13:43
$a = bcpowmod(2, 249, 997); echo $a."\n";Spravny vysledek 161. V pythonu s tim samym neni zadny problem:
print 2**249 % 997Vysledek opet spravne a uz asi chapete kam mirim. Kod v C:
long long x = ((long long)pow(a, d)) % n; printf("x=%lld\n",x);No a asi neprekvapi, ze dojde k preteceni zobrazi se zaporny vysledek. Moje otazka je, jak toto vyresit. Vim, ze existuji knihovny pro praci s velkymi cisli (libgmp), ale tem bych se hrozne rad vyhnul. Je nejaka moznost jak toho vyresit standardnimi prostredky C/C++?
Řešení dotazu:
print 2**249 % 997Otázka je jestli to počítá tak jak bys chtěl (kvůli rychlosti apod).
a^fi(n) % n = 1kde
fi(n)
je Eulerova funkce přirozeného čísla n
. A díky prioritě operací (mocnina je prioritnější než modulo, dělení a násobení) také patrně nevyužívá identity (a*b)%n = ((a%n)*(b%n))%nkterá umožňuje počítat modulo pro mnohem menší čísla než nejdříve pronásobit a pak dělit.
V 99,99% špatně, tedy pomalu a neoptimálně. Pochybuji, že by algoritmus do normálního vzorce měl aplikovánu čínskou větu o zbytcích a také téměř určitě implementace nevyužívá identityPython prakticky neoptimalizuje. Alespoň v současných verzích. Ale problém je v tom, že i kdybys chtěl takovýto výraz optimalizovat, tak by se musela vymýtit spousta zlozvyků jako používat stejné operátory na různé účely. A i tak by programátoři byli kolikrát překvapeni, co jejich program vlastně dělá. Python pracuje nad objekty a z objektů samotných zjišťuje, jak se mají dané operace provést. Na rychlé výpočty je mnohem lepší C, které se případně z Pythonu zavolá. Na druhou stranu na první pokusy a proof of concept implementace je Python ideální už díky podpoře velkých čísel.
a také téměř určitě implementace nevyužívá identitya^fi(n) % n = 1kdefi(n)
je Eulerova funkce přirozeného číslan
.
Vezmu-li v úvahu, že φ(997) = 996 > 249, tak v tom zase tak zásadní problém nevidím. Nemluvě o tom, že pokud exponent není opravdu výrazně větší než n, bude samotný výpočet φ(n) (časová náročnost obecně odmocnina z n) trvat déle než prostě tu mocninu spočítat v příslušném ℤ/ℤ[n] (časová náročnost logaritmická vzhledem k exponentu).
Tiskni
Sdílej:
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.