Ostatnio szybko się uczę, ale mam podstawowy problem, na który nie mogę znaleźć odpowiedzi
Chcę dostać coś takiego
var a:Int = 3
var b:Int = 3
println( pow(a,b) ) // 27
ale funkcja pow może działać tylko z podwójną liczbą, nie działa z liczbą całkowitą, a nie mogę nawet rzutować int na double przez coś takiego jak Double (a) lub a.double () ...
Dlaczego nie dostarcza mocy liczby całkowitej? na pewno zwróci liczbę całkowitą bez dwuznaczności! i dlaczego nie mogę rzucić liczby całkowitej na podwójną? po prostu zmień 3 na 3.0 (lub 3.00000 ... cokolwiek)
jeśli mam dwie liczby całkowite i chcę wykonać operację zasilania, jak mogę to zrobić płynnie?
Dzięki!
Odpowiedzi:
Jeśli chcesz, możesz zadeklarować, że
infix
operator
to zrobisz.Użyłem dwóch karetek, więc nadal możesz używać operatora XOR .
Aktualizacja dla Swift 3
W Swift 3 „magiczna liczba”
precedence
zostaje zastąpiona przezprecedencegroups
:źródło
infix operator ^^ { precedence 160 } func ^^
... i tak dalejfunc p(_ b: Bool) -> Double { return b?-1:1 }
?Poza tym, że deklaracje zmiennych mają błędy składniowe, działa to dokładnie tak, jak się tego spodziewałeś. Wszystko, co musisz zrobić, to rzucić
a
ib
podwoić i przekazać wartościpow
. Następnie, jeśli pracujesz z 2 Ints i chcesz, aby Int z powrotem po drugiej stronie operacji, po prostu rzuć z powrotem do Int.źródło
3 ** 3
. Czasami muszę rozwiązać problem z algorytmem za pomocą Swift, jest to naprawdę bolesne w porównaniu do używania Pythona.Czasami rzutowanie
Int
na aDouble
nie jest dobrym rozwiązaniem. Przy niektórych wielkościach w tej konwersji występuje utrata precyzji. Na przykład poniższy kod nie zwraca tego, czego można by się intuicyjnie spodziewać.Jeśli potrzebujesz precyzji przy dużych wielkościach i nie musisz martwić się o ujemne wykładniki - których i tak nie da się ogólnie rozwiązać za pomocą liczb całkowitych - to najlepszym rozwiązaniem jest ta implementacja algorytmu rekurencyjnego potęgowania ogona przez kwadrat . Zgodnie z tą odpowiedzią SO , jest to „standardowa metoda wykonywania modularnego potęgowania ogromnych liczb w kryptografii asymetrycznej”.
Uwaga: w tym przykładzie użyłem generycznego
T: BinaryInteger
. Dzięki temu możesz użyćInt
lubUInt
lub dowolnego innego typu podobnego do liczby całkowitej.źródło
Int
lub możesz mieć te rzeczy, które nazywają tę bezpłatną funkcję - cokolwiek dusza zapragnie.Jeśli naprawdę chcesz implementację „tylko int” i nie chcesz zmuszać do / z
Double
, musisz ją zaimplementować. Oto trywialna implementacja; istnieją szybsze algorytmy, ale to zadziała:W prawdziwej implementacji prawdopodobnie chciałbyś sprawdzić błędy.
źródło
Double(Int.max - 1) < Double(Int.max)
w Swift 3 REPL, a możesz być zaskoczony.reduce
połączenia.return (2...power).reduce(base) { result, _ in result * base }
trochę więcej szczegółów
swift - Wyrażenia binarne
źródło
Jeśli nie masz ochoty na przeciążanie operatorów (chociaż
^^
rozwiązanie jest prawdopodobnie jasne dla kogoś czytającego Twój kod), możesz wykonać szybką implementację:źródło
mklbtz ma rację co do potęgowania przez podniesienie do kwadratu, będącego standardowym algorytmem obliczania mocy całkowitych, ale rekurencyjna implementacja ogona algorytmu wydaje się nieco zagmatwana. Zobacz http://www.programminglogic.com/fast-exponentiation-algorithms/ dla nierekurencyjnej implementacji potęgowania przez podniesienie do kwadratu w C. Próbowałem przetłumaczyć to na Swift tutaj:
Oczywiście można to sobie wyobrazić, tworząc przeciążony operator, który będzie to wywoływał, i może zostać przepisany, aby uczynić go bardziej ogólnym, aby działał na wszystkim, co implementuje
IntegerType
protokół. Aby było to ogólne, prawdopodobnie zacząłbym od czegoś takiegoAle to prawdopodobnie daje się ponieść emocjom.
źródło
BinaryInteger
.IntegerType
został wycofany.Lub tylko :
źródło
Łączenie odpowiedzi w przeładowany zestaw funkcji (i używanie „**” zamiast „^^”, jak używają niektóre inne języki - jaśniejsze dla mnie):
Używając Float, możesz stracić precyzję. Jeśli używasz literałów numerycznych i kombinacji liczb całkowitych i niecałkowitych, domyślnie otrzymasz Double. Osobiście lubię możliwość używania wyrażenia matematycznego zamiast funkcji takiej jak pow (a, b) ze względów stylistycznych / czytelności, ale to tylko ja.
Każdy operator, który spowodowałby, że pow () wyrzuci błąd, spowoduje również, że te funkcje będą generować błąd, więc ciężar sprawdzania błędów i tak spoczywa na kodzie używającym funkcji power. KISS, IMHO.
Użycie natywnej funkcji pow () pozwala np. Wziąć pierwiastek kwadratowy (2 ** 0,5) lub odwrotnie (2 ** -3 = 1/8). Ze względu na możliwość użycia wykładników odwrotnych lub ułamkowych napisałem cały swój kod tak, aby zwracał domyślny typ Double funkcji pow (), który powinien zwracać największą precyzję (o ile dobrze pamiętam dokumentację). W razie potrzeby można to obniżyć do typu Int, Float lub cokolwiek innego, prawdopodobnie z utratą precyzji.
źródło
Okazuje się, że możesz również użyć
pow()
. Na przykład możesz użyć następującego wyrażenia, aby wyrazić 10 do 9.Wraz z
pow
,powf()
zwracafloat
zamiastdouble
. Przetestowałem to tylko w Swift 4 i macOS 10.13.źródło
Aby obliczyć
power(2, n)
, po prostu użyj:źródło
Wersja Swift 4.x.
źródło
W Swift 5:
Użyj w ten sposób
Dzięki odpowiedzi @Paul Buis.
źródło
Array (powtarzanie: a, count: b) .reduce (1, *)
źródło
Funkcja pow oparta na liczbach Int, która oblicza wartość bezpośrednio poprzez przesunięcie bitowe dla podstawy 2 w języku Swift 5:
(Upewnij się, że wynik mieści się w zakresie Int - to nie sprawdza przypadku poza zakresem)
źródło
Inne odpowiedzi są świetne, ale jeśli wolisz, możesz to również zrobić z
Int
przedłużeniem, o ile wykładnik jest dodatni.źródło
Próbując połączyć przeciążenie, próbowałem użyć leków generycznych, ale nie mogłem tego zrobić. W końcu doszedłem do wniosku, że zamiast próbować przeciążać lub używać leków generycznych, należy użyć NSNumber. Upraszcza to do następujących:
Poniższy kod jest tą samą funkcją co powyżej, ale implementuje sprawdzanie błędów, aby sprawdzić, czy parametry można pomyślnie przekonwertować na podwójne.
źródło
Szybki 5
Byłem zaskoczony, ale nie znalazłem tutaj odpowiedniego rozwiązania.
To jest moje:
Przykład:
źródło
To mi się bardziej podoba
źródło
Przykład:
źródło