Відповіді:
Для деякої кількості y
та деякого дільника x
обчисліть коефіцієнт ( quotient
) та решту ( remainder
) як:
var quotient = Math.floor(y/x);
var remainder = y % x;
floor
та %
разом не є таким чином. Або використовуйте trunc
замість floor
(дозволяючи тим самим негативні залишки), або використовуйте віднімання, щоб отримати залишок ( rem = y - div * x
).
rem
будь-якому випадку, ви можете отримати приватне div
швидше без статі: (y - rem) / x
. 2. До речі, операція з модулем за рекомендованим визначенням Дональда Кнута (роздільник знаків-відповідників, а не решта, тобто модуль Евкліда, ані JavaScript-знак-відповідність-дивіденд) - це те, що ми можемо кодувати в JavaScript function mod (a, n) { return a % n + (Math.sign(a) !== Math.sign(n) ? n : 0); }
.
Я не фахівець з розрядних операторів, але ось ще один спосіб отримати цілу кількість:
var num = ~~(a / b);
Це буде справно працювати і за від’ємними числами, тоді як Math.floor()
буде закруглено в неправильному напрямку.
Це також здається правильним:
var num = (a / b) >> 0;
a/b | 0
~~int
, int | 0
і int >> 0
не змінює початковий аргумент, але змушує інтерпретатор передавати невід'ємну частину оператору.
floor
навряд чи крутить у неправильному напрямку, даючи свою назву - просто не той напрямок, якого хочуть люди взагалі!
a = 12447132275286670000; b = 128
Math.floor(a/b)
-> 97243220900677100
і ~~(a/b)
-> -1231452688
.
~~(5/2) --> 2
як це (5/2)>>0 --> 2
, але ~~(5/2) + 1 --> 3
, поки ~~(5/2)>>0 + 1 --> 1
. ~~
є хорошим вибором, оскільки пріоритет є більш доречним.
Я зробив кілька тестів на швидкість на Firefox.
-100/3 // -33.33..., 0.3663 millisec
Math.floor(-100/3) // -34, 0.5016 millisec
~~(-100/3) // -33, 0.3619 millisec
(-100/3>>0) // -33, 0.3632 millisec
(-100/3|0) // -33, 0.3856 millisec
(-100-(-100%3))/3 // -33, 0.3591 millisec
/* a=-100, b=3 */
a/b // -33.33..., 0.4863 millisec
Math.floor(a/b) // -34, 0.6019 millisec
~~(a/b) // -33, 0.5148 millisec
(a/b>>0) // -33, 0.5048 millisec
(a/b|0) // -33, 0.5078 millisec
(a-(a%b))/b // -33, 0.6649 millisec
Вищезазначене спирається на 10 мільйонів випробувань для кожного.
Висновок: Використовуйте (a/b>>0)
(або (~~(a/b))
або (a/b|0)
), щоб досягти 20% приросту ефективності. Також майте на увазі, що всі вони суперечать Math.floor
, коли a/b<0 && a%b!=0
.
Math.floor
а також, хто знає, як багато інших функцій API, або дізнатися про ~
(бітовий-не) оператор і як бітові операції працюють у JS, а потім зрозуміти ефект подвійного нахилу?
Math.floor
краще. І навіть якщо ні, цей є гугл.
ES6 представляє новий Math.trunc
метод. Це дозволяє виправити відповідь @ MarkElliot, щоб вона також працювала і за від’ємними числами:
var div = Math.trunc(y/x);
var rem = y % x;
Зауважте, що Math
методи мають перевагу над бітовими операторами, що вони працюють з числами понад 2 31 .
18014398509481984 == 18014398509481985
.
~~(x/y)
. Вам потрібно підтримувати більшу кількість до 54 біт, підписаних? Використовуйте, Math.trunc
якщо у вас є, або Math.floor
іншим способом (правильно для від'ємних чисел). Вам потрібно підтримувати ще більшу кількість? Використовуйте бібліотеку великих чисел
divmod
, ви можете реалізувати це як таке:function divmod(x, y) { var div = Math.trunc(x/y); var rem = x % y; return [div, rem]; }
var remainder = x % y;
return (x - remainder) / y;
Math.trunc
:). Я перевірив зі 100,3; -100,3; 100, -3 і -100, -3. Звичайно, минуло багато часу з моменту вашого коментаря, і все зміниться.
Я зазвичай використовую:
const quotient = (a - a % b) / b;
const remainder = a % b;
Це, мабуть, не найелегантніше, але це працює.
Ви можете використовувати цю функцію parseInt
для отримання усіченого результату.
parseInt(a/b)
Щоб отримати залишок, використовуйте оператор мод:
a%b
parseInt мають деякі підводні камені з рядками, щоб уникнути використання параметра radix з базою 10
parseInt("09", 10)
У деяких випадках рядкове представлення числа може бути науковим позначенням, в цьому випадку parseInt дасть неправильний результат.
parseInt(100000000000000000000000000000000, 10) // 1e+32
Цей виклик дасть 1 результат.
parseInt
слід уникати, коли це можливо. Ось попередження Дугласа Крокфорда: "Якщо перший символ рядка дорівнює 0, то рядок оцінюється в базі 8 замість основи 10. У базі 8 8 і 9 не є цифрами, тому parseInt (" 08 ") і parseInt ("09") отримують 0 як результат. Ця помилка спричиняє проблеми в програмах, які розбирають дати та часи. На щастя, parseInt може приймати параметр radix, так що parseInt ("08", 10) видає 8. Я рекомендую вам завжди надати параметр radix. " archive.oreilly.com/pub/a/javascript/excerpts/…
parseInt
слід уникати; просто, що є деякі готчі, про які слід знати. Ви повинні бути в курсі цих речей і бути готовими впоратися.
parseInt
з аргументом числа. parseInt
повинен розбирати частково числові рядки, а не усікати числа.
JavaScript обчислює праву підлогу від'ємних чисел та решту нецілих чисел, дотримуючись математичних визначень для них.
FLOOR визначається як "найбільше ціле число, менше параметра", таким чином:
REMAINDER визначається як "залишений" ділення (арифметика Евкліда). Коли дивіденд не є цілим числом, частник зазвичай також не є цілим числом, тобто немає залишку, але якщо коефіцієнт змушений бути цілим числом (і саме це відбувається, коли хтось намагається отримати залишок або модуль цілого число з плаваючою комою), очевидно, буде не ціле число "залишилося".
JavaScript обчислює все так, як очікувалося, тому програміст повинен бути обережним, щоб задати відповідні запитання (а люди повинні бути обережні, щоб відповісти на запитання!) Першим запитанням Яріна НЕ було "що це ціле ділення X на Y", але, натомість "ЦІЛЬКА кількість разів дане ціле число ВИДАЄ В інше". Для позитивних чисел відповідь однакова для обох, але не для від'ємних чисел, тому що ціле ділення (дивіденд на дільник) буде на -1 менше, ніж раз, коли число (дільник) "переходить" в інше (дивіденд). Іншими словами, FLOOR поверне правильну відповідь на ціле ділення від'ємного числа, але Ярін цього не запитувала!
gammax відповів правильно, що код працює так, як запитав Ярін. З іншого боку, Самуель помиляється, він не займався математикою, я думаю, або він би бачив, що це працює (також, він не сказав, що було дільником його прикладу, але я сподіваюся, що це було 3):
Залишок = X% Y = -100% 3 = -1
GoesInto = (X - залишок) / Y = (-100 - -1) / 3 = -99 / 3 = -33
До речі, я тестував код на Firefox 27.0.1, він працював, як і очікувалося, з позитивними та від’ємними числами, а також із нецілими значеннями, як для дивіденду, так і для дільника. Приклад:
-100,34 / 3,57: GoesInto = -28, залишок = -0,3800000000000079
Так, я помітив, там є проблема точності, але я не встиг її перевірити (не знаю, чи це проблема з Firefox, Windows 7 або FPU мого процесора). Для запитання Яріна, що стосується лише цілих чисел, код гаммакса працює чудово.
Math.floor(operation)
повертає округлене значення операції.
Приклад 1 - й питання:
var x = 5;
var y = 10.4;
var z = Math.floor(x + y);
console.log(z);
Консоль:
15
Приклад 2 - й питання:
var x = 14;
var y = 5;
var z = Math.floor(x%y);
console.log(x);
Консоль:
4
Обчислення кількості сторінок може бути виконано за один крок: Math.ceil (x / y)
Коментар Алекса Мура-Ніємі як відповідь:
Для рубістів тут від Google divmod
, ви можете їх реалізувати як таке:
function divmod(x, y) {
var div = Math.trunc(x/y);
var rem = x % y;
return [div, rem];
}
Результат:
// [2, 33]
divmod
використовується флоральний поділ ( Math.floor
), який відрізняється від усіченого поділу ( Math.trunc
), коли задіяні негативні числа. Це стосується пакету NPMdivmod
, Rubydivmod
, SWI-Prologdivmod
і, мабуть, багатьох інших реалізацій.
divmod
існує, оскільки воно виконує вдвічі швидше, ніж обчислення двох операцій окремо. Надання такої функції без цієї переваги може бути заплутаною.
Якщо ви просто ділите з двома потужностями, ви можете використовувати побітові оператори:
export function divideBy2(num) {
return [num >> 1, num & 1];
}
export function divideBy4(num) {
return [num >> 2, num & 3];
}
export function divideBy8(num) {
return [num >> 3, num & 7];
}
(Перший - коефіцієнт, другий - решта)
function divideByPowerOf2(num, exponent) { return [num >> exponent, num & ((1 << exponent) - 1)]; }
.
Ви можете використовувати термінал, щоб вирішити, як обробляти додатні та негативні цілі значення.
var myInt = (y > 0) ? Math.floor(y/x) : Math.floor(y/x) + 1
Якщо число позитивне, все добре. Якщо число від’ємне, воно додасть 1 через те, як Math.floor обробляє негативи.
Це завжди скорочуватиметься до нуля. Не впевнений, чи не пізно, але ось так:
function intdiv(dividend, divisor) {
divisor = divisor - divisor % 1;
if (divisor == 0) throw new Error("division by zero");
dividend = dividend - dividend % 1;
var rem = dividend % divisor;
return {
remainder: rem,
quotient: (dividend - rem) / divisor
};
}
Якщо вам потрібно обчислити залишок для дуже великих цілих чисел, які час виконання JS не може представляти як таке (будь-яке ціле число, що перевищує 2 ^ 32, представлено у вигляді поплавця і тому воно втрачає точність), вам потрібно зробити якийсь трюк.
Це особливо важливо для перевірки багатьох випадків чекових цифр, які є у багатьох випадках нашого повсякденного життя (номери банківських рахунків, кредитні картки, ...)
Перш за все, ваш номер потрібен як рядок (інакше ви вже втратили точність, а решта не має сенсу).
str = '123456789123456789123456789'
Тепер вам потрібно розділити рядок на більш дрібні частини, досить малі, щоб з'єднання будь-якого залишку та шматка рядка могло вміститися в 9 цифр.
digits = 9 - String(divisor).length
Підготуйте регулярний вираз для розділення рядка
splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g')
Наприклад, якщо digits
це 7, регулярне вираження є
/.{1,7}(?=(.{7})+$)/g
Він відповідає непустому підрядку максимальної довжини 7, за яким слідує ( (?=...)
є позитивним підказкою) число символів, кратне 7. 7. 'g' - це зробити вираз пробігати через весь рядок, не зупиняючись при першій відповідності.
Тепер перетворіть кожну частину на ціле число і обчисліть залишки за допомогою reduce
(додаючи назад попередній залишок - або 0 - помножений на правильну потужність 10):
reducer = (rem, piece) => (rem * Math.pow(10, digits) + piece) % divisor
Це спрацює через алгоритм залишку віднімання:
n mod d = (n - kd) mod d
що дозволяє замінити будь-яку "початкову частину" десяткового подання числа на його решту, не впливаючи на остаточну залишок.
Кінцевий код виглядатиме так:
function remainder(num, div) {
const digits = 9 - String(div).length;
const splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g');
const mult = Math.pow(10, digits);
const reducer = (rem, piece) => (rem * mult + piece) % div;
return str.match(splitter).map(Number).reduce(reducer, 0);
}
3.5 % 2
оцінює до 1,5. Обов’язково обробіть (parseInt, floor тощо) за необхідності