Natknąłem się na to wyzwanie na Edabit i nie mogłem znaleźć tego rozwiązania operacji bitowej.
notNotNot = (a,b) => !!(a%2 >> b)
Wyzwanie:
//Something which is not true is false, but something which is not not true is true!
//Create a function where given n number of "not", evaluate whether it's true or false.
//Examples:
notNotNot(1, true) ➞ false
// Not true
notNotNot(2, false) ➞ false
// Not not false
notNotNot(6, true) ➞ true
// Not not not not not not true
Zrobiłem badania, które ten operator:
Przesuwa w prawo, popychając kopie najbardziej wysuniętego w lewo bitu od lewej i pozwól, aby bity najbardziej wysunięte w prawo wypadły.
Wydaje mi się, że zrozumiałem (np. To 5 >> 1
samo, 0101 >> 1
co ocenia 0010
), ale nie widzę, jak to działa z wartością logiczną? Wiem, że true
ocenia 1
i false
do 0
.
javascript
kiabbott
źródło
źródło
true
=1
(dziesiętny) =01
(dwójkowy) przesunięty w lewo o jeden spowoduje10
binarny lub2
dziesiętny.notNotNot(2, true)
: powrócifalse
, ale nieprawda (!!true
) powinna byćtrue
...false
należy rozstrzygnąćtrue
.notNotNot = (a,b) => !!((a%2)^b)
zamiast tego ...(a, b) => !!((a + b) % 2)
?Odpowiedzi:
Podana funkcja nie spełnia wyzwania. Właściwa zmiana biegów nie spełni oczekiwań. Na przykład twój
notNotNot(6,true)
jestfalse
, nietrue
w momencie oddania za pośrednictwem funkcji.Twoje pytanie dotyczy bitowej operacji na wartości logicznej. Ponieważ operatorzy lubią
>>
i<<
pracują na liczbach całkowitych, Javascript najpierw konwertuje wartość logiczną na liczbę całkowitą. Więctrue
staje się 1 ifalse
staje się 0. Aby to zobaczyć, możesz przesunąć o zero:Używanie
!!
to przydatny sposób na konwersję czegokolwiek na wartość logiczną. To trwa niczego, co mogłoby być uznane za równoważne z false (takich jak 0,null
,undefined
lub „”) i daje z powrotemfalse
. Podobnie wszystko, co jest prawdą (jak 14, „cześć”, [4], {a: 1}) i oddajtrue
.!!
działa, ponieważ pierwszy wykrzyknik podaje „nie” wyrażenia, które jest zawszetrue
lubfalse
, a następnie drugi wykrzyknik daje przeciwieństwo tego (false
lubtrue
).Wracając do wyzwania, chce zastosować czasy nie będące operatorem „a” i porównać je z wartością „b”. Więc coś takiego działałoby:
źródło
if (a % 2 === 1) return !b else return b
to, jak pokazano w innych odpowiedziach, istnieją sposoby, aby to zrobić bez rozgałęzień lub pętli.Operatory bitowe zawsze przekształcają operandy na liczby całkowite. Tak więc
4 >> true
jest to to samo,4 >> 1
co spowoduje nieznaczne przesunięcie w prawo o jedną pozycjęTak więc użycie
true
lubfalse
jest tylko rondem do użycia1
lub0
.notNotNot
Funkcja ma bardzo prostą obsługę, ogólnie:a%2
konwertuje pierwszą liczbę na0
parzystą lub1
nieparzystą.>> b
przesuwa się w prawo o0
pozycje dlafalse
lub1
pozycję dlatrue
.a
jest nieparzysty (1) ib
wynosifalse
=1
a
jest nieparzysty (1) ib
wynositrue
=0
1
jest przesunięty w prawo i odrzucony.a
jest parzysty (0) ib
wynosifalse
=0
a
jest parzysty (0) ib
wynositrue
=0
0
który nie ma ustawionych bitów, więc przesunięcie w prawo dowolnej kwoty nie zmienia tego.!!()
konwertuje wynik na wartość logiczną.Powiedziawszy to, rozwiązanie tutaj jest złe, ponieważ
notNotNot(2, true)
spowoduje , żefalse
-a
będzie parzyste ib
jesttrue
. Oczekuje się, żetrue
od tego czasu będzie produkować!!true = true
. Ten sam problem występuje w przypadku dowolnej liczby parzystej itrue
.Można to łatwo naprawić za pomocą bitowego XOR zamiast prawego przesunięcia:
a
jest nieparzysty (1) ib
wynosifalse
=1
0
a
jest nieparzysty (1) ib
wynositrue
=0
1
a
jest parzysty (0) ib
wynosifalse
=0
0
a
jest parzysty (0) ib
wynositrue
=1
1
Dla zachowania kompletności, na wypadek, gdybyś chciał wykonać operację w pełni bitową:
Operację modulo
%2
można zmienić na bitową ORAZ&1
uzyskać najniższy bit. W przypadku liczb parzystych przyniosłoby to wynik,0
ponieważ będziesz obliczałktóra wynosi zero. W przypadku liczb nieparzystych obowiązuje to samo, ale w rezultacie otrzymasz jeden:
Więc wyniki
a&1
ia%2
są identyczne. Co więcej, nawet jeśli operacje bitowe przekształcają liczbę na 32-bitową liczbę całkowitą ze znakiem, co nie ma znaczenia, ponieważ zachowana byłaby parzystość .Pokaż fragment kodu
źródło
Po pierwsze,
(a,b) => !!(a%2 >> b)
nie pasuje do wyników z przykładów. Podzielę dokładnie to, co robi przy użyciunotNotNot(6, true) ➞ true
.a%2
, po prostua
podziel się przez 2, zwróć resztę. Otrzymamy więc 0 za liczbę parzystą i 1 za liczbę nieparzystą.a = 6
a%2 = 0
w tym przypadku.0 >> b
przesuń 1 cyfrę w prawo, ponieważ, jak powiedziałeś,true
ocenia1
. Więc rozumiemy0 >> 1 = 0
.!!(0)
, jest prosta i można rozbić jak tak!0 = true
, to!true = false
.Jeśli więc zastanowimy się nad tym tak długo, jak
b
totrue
będzie możliwe, zawsze wrócimyfalse
. Powiedzmy, że mamy a = 5, b = true do oceny5%2 = 1
,1 >> 1 = 0
. Możesz zobaczyć ze względu na mod (%2
), będziemy mieć tylko 1 lub 0 (zawsze tylko 1 cyfrę), a true zawsze zmieni wartość 1, gdy ją mamy.Prosty sposób spojrzenia na ten problem jest jak
isEvenOrNot
funkcja. Podobniea
jest z liczbą, którą sprawdzamy ib
jest wartością logiczną, aby sprawdzić, czy jest parzysta (prawda), czy nawet parzysta (fałsz). Działa to, ponieważ każdanot
dodana sekunda będzie prawdziwa.Więc rozwiązanie używając bitowego może być coś takiego:
(a,b) => !!(a&1 ^ b)
. Pozwól, że będziesz się dobrze bawić z podziałem, dlaczego to działa! :)Nieco więcej na temat wyjaśniania, jak shift działa z wartością logiczną. Tak
true
jak powiedziałeś, będzie 1, a fałsz będzie 0. Tak jak pokazano w twoim przykładzie,0101 >> true
jest to samo co0101 >> 1
.Mam nadzieję, że to pomoże.
Użyłem następującego jako odniesienia dla bitowego: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators
źródło
Uwaga: Dla obu wartości logicznych parzysta liczba NOT powoduje powstanie oryginalnej wartości logicznej, a nieparzysta liczba NOT daje przeciwną wartość logiczną
LSB dowolnej liczby decyduje, czy liczba jest nieparzysta, czy parzysta. (0 parzysta, 1 nieparzysta)
źródło
Widzę, że twoim zadaniem jest:
Nie wiem dlaczego piszesz
notnotnot
dla mnie funkcję, o którą nie prosi zadanie.Więc zgodnie z zadaniem wykonałem tę funkcję
not
która akceptuje wiele „not” i je ocenia.Pierwszy sposób
Drugi sposób przy użyciu XOr (^)
Trzeci sposób korzystania z Mod (%) wskazany przez @VLAZ
Czwarty sposób użycia bitowego And (&)
Test
źródło
n
- tylko czy jest parzysta czy nieparzysta, ponieważ dowolne dwa NIE anulują, więc!!!!!b
jest to samo co!b
. Dlatego nie potrzebujemy pętli, jeśli tylko weźmiemyn%2
- dostalibyśmy1
za NIE i0
za „zachowaj to samo”. Ponieważ mamy liczbę, możemy po prostu wykonywać operacje bitowe.Najpierw pozwala na analizę
Teraz przeanalizuj dla
(a,b) => !!(a%2 >> b)
Ów środek ten nie działa dla
notNotNot(6, true)
totrue
jednak obecne rozwiązanie dajefalse
.Możemy
^
(XOR) operator, aby poprawić. Like(a,b) => !!(a%2 ^ b)
Teraz przeanalizuj dla
(a,b) => !!(a%2 ^ b)
Przykład:
źródło