W JavaScript , jak mogę dostać:
- Ile razy dana liczba całkowita przechodzi w inną?
- Reszta?
W JavaScript , jak mogę dostać:
Dla pewnej liczby y
i dzielnika x
oblicz iloraz ( quotient
) i resztę ( remainder
) jako:
var quotient = Math.floor(y/x);
var remainder = y % x;
3.5 % 2
ocenia na 1.5. Upewnij się, żefloor
i%
razem nie jest spójne w ten sposób. Albo użyjtrunc
zamiastfloor
(umożliwiając w ten sposób ujemne resztki), albo użyj odejmowania, aby otrzymać resztę (rem = y - div * x
).rem
tak, można dostać ilorazdiv
szybciej bez podłogi:(y - rem) / x
. 2. Nawiasem mówiąc, operacja modulo według zalecanej definicji Donalda Knutha (dzielnik znaków dopasowania, a nie reszta, tj. Moduł euklidesowy, ani znak dywidendy znaków JavaScript) jest tym, co możemy zakodować w JavaScript jakofunction mod (a, n) { return a % n + (Math.sign(a) !== Math.sign(n) ? n : 0); }
.Nie jestem ekspertem od operatorów bitowych, ale oto inny sposób na uzyskanie całej liczby:
Działa to również poprawnie dla liczb ujemnych, a
Math.floor()
zaokrągla w niewłaściwym kierunku.To również wydaje się poprawne:
źródło
a/b | 0
~~int
,int | 0
Iint >> 0
nie zmienia Pierwszym argumentem, ale sprawiają, że integralną część interpretera przechodzi do operatora.floor
prawie nie krąży w złym kierunku, biorąc pod uwagę jego nazwę - po prostu nie w kierunku, który ludzie na ogół chcą!a = 12447132275286670000; b = 128
Math.floor(a/b)
->97243220900677100
i~~(a/b)
->-1231452688
.~~(5/2) --> 2
jak to robi(5/2)>>0 --> 2
, ale~~(5/2) + 1 --> 3
jednocześnie~~(5/2)>>0 + 1 --> 1
.~~
jest dobrym wyborem, ponieważ pierwszeństwo jest bardziej odpowiednie.Zrobiłem kilka testów prędkości w Firefoksie.
Powyższe opiera się na 10 milionach prób dla każdego.
Wniosek: Użyj
(a/b>>0)
(lub(~~(a/b))
lub(a/b|0)
), aby osiągnąć około 20% przyrost wydajności. Należy także pamiętać, że są one niezgodne zMath.floor
kiedya/b<0 && a%b!=0
.źródło
Math.floor
wielu innych funkcji API i kto wie, ile funkcji API, lub poznanie~
operatora (bitowego-nie) i tego, jak działają operacje bitowe w JS, a następnie zrozumienie efektu podwójnej tyldy?Math.floor
lepiej to zrozumieją . A nawet jeśli nie, ten jest dostępny w Google.ES6 wprowadza nową
Math.trunc
metodę. Pozwala to naprawić odpowiedź @ MarkElliot, aby działała również dla liczb ujemnych:Zauważ, że
Math
metody mają przewagę nad operatorami bitowymi, ponieważ pracują z liczbami powyżej 2 31 .źródło
18014398509481984 == 18014398509481985
.~~(x/y)
. Potrzebujesz obsługi większej liczby podpisanych do 54 bitów? Użyj,Math.trunc
jeśli go masz, lub wMath.floor
inny sposób (popraw dla liczb ujemnych). Potrzebujesz obsługi nawet większych liczb? Użyj biblioteki dużej liczby.divmod
, możesz zaimplementować go jako taki:function divmod(x, y) { var div = Math.trunc(x/y); var rem = x % y; return [div, rem]; }
źródło
Math.trunc
:). Sprawdziłem za pomocą 100,3; -100,3; 100, -3 i -100, -3. Oczywiście minęło wiele czasu od twojego komentarza i rzeczy się zmieniają.Zwykle używam:
To chyba nie jest najbardziej elegancki, ale działa.
źródło
Możesz użyć tej funkcji,
parseInt
aby uzyskać obcięty wynik.Aby uzyskać resztę, użyj operatora mod:
parseInt ma pewne pułapki z łańcuchami, aby uniknąć użycia parametru radix z bazą 10
W niektórych przypadkach ciąg znaków reprezentujący liczbę może być notacją naukową, w tym przypadku parsowanie spowoduje niepoprawny wynik.
W wyniku tego wywołanie wygeneruje 1.
źródło
parseInt
w miarę możliwości należy tego unikać. Oto ostrzeżenie Douglasa Crockforda: „Jeśli pierwszym znakiem ciągu jest 0, to łańcuch jest przetwarzany w podstawie 8 zamiast w podstawie 10. W bazie 8, 8 i 9 nie są cyframi, więc parsuj („ 08 ”) i parsuj („09”) dają wynik 0. Błąd ten powoduje problemy w programach, które analizują daty i godziny. Na szczęście parseInt może przyjąć parametr radix, więc parseInt („08”, 10) daje 8. Zalecam, abyś zawsze podaj parametr radix. ” archive.oreilly.com/pub/a/javascript/excerpts/…parseInt
należy go unikać; po prostu trzeba pamiętać o kilku problemach. Musisz zdawać sobie sprawę z tych rzeczy i być przygotowanym na poradzenie sobie.parseInt
z argumentem liczbowym.parseInt
ma analizować ciągi częściowo numeryczne, a nie obcinać liczby.JavaScript oblicza na podstawie dolnej liczby liczb ujemnych i pozostałej liczby niecałkowitej, zgodnie z ich matematycznymi definicjami.
FLOOR jest zdefiniowany jako „największa liczba całkowita mniejsza niż parametr”, a zatem:
REMAINDER jest zdefiniowany jako „pozostały” podziału (arytmetyka euklidesowa). Gdy dywidenda nie jest liczbą całkowitą, iloraz zwykle nie jest również liczbą całkowitą, tzn. Nie ma reszty, ale jeśli iloraz jest zmuszony do bycia liczbą całkowitą (i tak się dzieje, gdy ktoś próbuje uzyskać resztę lub moduł liczba zmiennoprzecinkowa), oczywiście pozostanie „liczba całkowita”.
JavaScript oblicza wszystko zgodnie z oczekiwaniami, więc programista musi uważnie zadawać właściwe pytania (a ludzie powinni uważać, aby odpowiedzieć na to, co jest zadawane!) Pierwsze pytanie Yarina brzmiało NIE „jaki jest całkowity podział X na Y”, ale: zamiast tego „CAŁA liczba przypadków, gdy dana liczba całkowita PRZEJDZIE DO INNEJ”. W przypadku liczb dodatnich odpowiedź jest taka sama dla obu, ale nie dla liczb ujemnych, ponieważ podział na liczby całkowite (dywidenda przez dzielnik) będzie -1 mniejszy niż czas, w którym liczba (dzielnik) „przechodzi” na inną (dywidenda). Innymi słowy, FLOOR zwróci poprawną odpowiedź dla liczb całkowitych liczb ujemnych, ale Yarin o to nie pytał!
gammax odpowiedział poprawnie, że kod działa zgodnie z zapytaniem Yarina. Z drugiej strony, Samuel się myli, chyba nie zrobił matematyki, bo inaczej zobaczyłby, że to działa (nie powiedział też, jaki był dzielnik jego przykładu, ale mam nadzieję, że tak było 3):
Reszta = X% Y = -100% 3 = -1
GoesInto = (X - pozostały) / Y = (-100 - -1) / 3 = -99 / 3 = -33
Nawiasem mówiąc, przetestowałem kod w przeglądarce Firefox 27.0.1, działał on zgodnie z oczekiwaniami, z liczbami dodatnimi i ujemnymi, a także z wartościami niecałkowitymi, zarówno dla dywidendy, jak i dzielnika. Przykład:
-100,34 / 3,57: GoesInto = -28, reszta = -0,3800000000000079
Tak, zauważyłem, że jest tam problem z precyzją, ale nie miałem czasu go sprawdzić (nie wiem, czy to problem z Firefoksem, Windows 7 lub z FPU mojego procesora). W przypadku pytania Yarina, które dotyczy tylko liczb całkowitych, kod gammax działa doskonale.
źródło
Math.floor(operation)
zwraca zaokrągloną wartość operacji.Przykład 1 st pytania:
Konsola:
Przykład drugiego pytania:
Konsola:
źródło
Obliczanie liczby stron można wykonać w jednym kroku: Math.ceil (x / y)
źródło
Komentarz Alexa Moore-Niemiego jako odpowiedź:
Dla rubyistów tutaj z Google w poszukiwaniu
divmod
, możesz zaimplementować go jako taki:Wynik:
źródło
divmod
używa dzielnika dzielonego (Math.floor
), który różni się od skróconego dzielenia (Math.trunc
), gdy występują liczby ujemne. Tak jest w przypadku pakietu NPMdivmod
, Rubydivmod
, SWI-Prologdivmod
i prawdopodobnie wielu innych implementacji.divmod
istnieje, ponieważ wykonuje się go dwa razy szybciej niż osobne obliczenie dwóch operacji. Zapewnienie takiej funkcji bez tej korzyści w zakresie wydajności może być mylące.Jeśli dzielisz tylko potęgami dwóch, możesz użyć operatorów bitowych:
(Pierwszy to iloraz, drugi to reszta)
źródło
function divideByPowerOf2(num, exponent) { return [num >> exponent, num & ((1 << exponent) - 1)]; }
.Możesz użyć trójskładnika, aby zdecydować, jak obsługiwać dodatnie i ujemne wartości całkowite.
Jeśli liczba jest dodatnia, wszystko jest w porządku. Jeśli liczba jest ujemna, dodaje 1, ponieważ Math.floor obsługuje negatywy.
źródło
To zawsze skróci się do zera. Nie jestem pewien, czy jest za późno, ale oto:
źródło
Jeśli musisz obliczyć resztę dla bardzo dużych liczb całkowitych, których środowisko wykonawcze JS nie może reprezentować jako takie (każda liczba całkowita większa niż 2 ^ 32 jest reprezentowana jako liczba zmiennoprzecinkowa, a zatem traci precyzję), musisz zrobić jakąś sztuczkę.
Jest to szczególnie ważne przy sprawdzaniu wielu przypadków cyfr czekowych, które są obecne w wielu przypadkach naszego codziennego życia (numery kont bankowych, karty kredytowe, ...)
Przede wszystkim potrzebujesz numeru jako łańcucha (w przeciwnym razie straciłeś już precyzję, a reszta nie ma sensu).
Teraz musisz podzielić sznurek na mniejsze części, wystarczająco małe, aby konkatenacja każdej pozostałej części i kawałka sznurka mieściła się w 9 cyfrach.
Przygotuj wyrażenie regularne, aby podzielić ciąg
Na przykład, jeśli
digits
jest to 7, wyrażenie regularne toOdpowiada niepustemu podciągowi o maksymalnej długości 7, po którym następuje (
(?=...)
jest to znak z wyprzedzeniem) liczba znaków, która jest wielokrotnością liczby 7. „g” powoduje, że wyrażenie przechodzi przez cały ciąg, nie zatrzymując się przy pierwszym dopasowaniu.Teraz przekonwertuj każdą część na liczbę całkowitą i oblicz resztę przez
reduce
(dodając poprzednią resztę - lub 0 - pomnożoną przez prawidłową moc 10):Działa to z powodu algorytmu reszty „odejmowania”:
który pozwala zastąpić dowolną „początkową część” dziesiętnej reprezentacji liczby jej pozostałą częścią, bez wpływu na końcową resztę.
Ostateczny kod wyglądałby następująco:
źródło