JavaScript에서 나머지를 가진 정수 나누기?


답변:


1239

일부 수 y와 일부 제수의 x경우 몫 ( quotient)과 나머지 ( remainder)를 다음과 같이 계산하십시오 .

var quotient = Math.floor(y/x);
var remainder = y % x;

84
%는 JavaScript의 부동 소수점에서 작동합니다 (다른 언어와는 다름) 3.5 % 2. 바람직하지 않은 경우 1.5로 평가됩니다. 필요에 따라 (parseInt, floor 등) 처리하십시오.

16
수학에서 -4.5의 정수 부분은 -5입니다. -5는 "-4.5보다 낮은 가장 높은 정수"입니다.
Toughy December

9
그러나 음수에 대해 결정한 것은 몫과 나머지에 걸쳐 일관성이 있어야합니다. 그런 식으로 사용 floor하고 %함께 사용하는 것은 일관성이 없습니다. 하나를 사용 trunc하는 대신 floor(따라서 부정적인 나머지를 허용) 또는 사용 뺄셈이 나머지를 얻기 위해 ( rem = y - div * x).
Mark Reed

7
1. rem어쨌든 나머지를 계산하려면 div바닥없이 몫을 더 빨리 얻을 수 있습니다 (y - rem) / x. 그런데 Donald Knuth의 권장 정의 (나머지 유클리드 모듈러스 나 JavaScript 부호 일치 배당이 아닌 부호 일치 나누기)에 의한 모듈로 연산은 JavaScript로 코딩 할 수있는 것 function mod (a, n) { return a % n + (Math.sign(a) !== Math.sign(n) ? n : 0); }입니다.
Aaron Mansheim 17

1
-9/2 = -4.5. 그런 다음 -4.5의 바닥, 즉 -5를 가져옵니다. -5는 -4.5보다 작고 바닥 연산은 주어진 값보다 작은 가장 큰 정수로 정의됩니다.
Mark Reed

371

나는 비트 연산자에 전문가가 아니지만 정수를 얻는 또 다른 방법이 있습니다.

var num = ~~(a / b);

음수에도 올바르게 작동하지만 Math.floor()잘못된 방향으로 반올림됩니다.

이것도 올바른 것 같습니다 :

var num = (a / b) >> 0;

84
지난 20 분 동안 알아 내려고했던 또 다른 목적은 분명히a/b | 0
BlueRaja-Danny Pflughoeft

18
@ user113716 @BlueRaja 비트 단위 연산은 정수 유형에서만 의미가 있으며 JS는 (물론) 알고 있습니다. ~~int, int | 0int >> 0초기 인수를 수정하지 않지만, 통역 운영자에게 중요한 부분을 통과합니다.
Aleksei Zabrodskii

15
floor사람들이 일반적으로 원하는 방향이 아니라 이름이 주어지면 잘못된 방향으로 반올림하지 않습니다!
Mark K Cowan

19
그것은 buu buu입니다. a = 12447132275286670000; b = 128 Math.floor(a/b)-> 97243220900677100~~(a/b)-> -1231452688.
Mirek Rusin

7
우선주의하십시오. ~~(5/2) --> 2AS는 않습니다 (5/2)>>0 --> 2만, ~~(5/2) + 1 --> 3반면, ~~(5/2)>>0 + 1 --> 1. ~~우선 순위가 더 적절하기 때문에 좋은 선택입니다.
timkay

217

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

위의 내용은 각각 1 천만 건의 시험을 기반으로합니다.

결론 :(a/b>>0) (또는 (~~(a/b))또는 (a/b|0))를 사용 하여 약 20 %의 효율성을 얻을 수 있습니다. 또한 Math.floor, 언제 에도 모두 일치하지 않습니다 a/b<0 && a%b!=0.


54
속도에 대해 정수 나누기를 최적화 하면 많이 수행하는 경우에만 의미 가 있습니다 . 다른 경우에는 가장 간단한 것을 선택하는 것이 좋습니다 (당신과 동료에게 가장 간단한 것).
mik01aj

7
@ m01은 전적으로 동의합니다-온라인과 같은 것들에 너무 많은 초점이 있습니다
JonnyRaa

2
@ m01 그러나 어느 것이 더 어려운가 : Math.floor다른 API 함수에 대해 배우고 누가 알 수있는 방법, 또는 ~(비트 단위가 아닌) 연산자 에 대해 배우고 JS에서 비트 단위 연산이 어떻게 작동하고 이중 물결표의 효과 를 이해 하는가?
Stijn de Witt

11
동료가 어셈블러에서 칩을 프로그래밍하지 않으면 Math.floor더 잘 이해할 것 입니다. 그리고 그렇지 않더라도 이것은 구글 가능합니다.
mik01aj

2
@MarkGreen 네.하지만 그렇게하고 싶다고해서 좋은 이유없이 가장 빠르기 때문에 이상한 형태로 작성해야한다는 의미는 아닙니다. 일반적으로 코드 선명도가 일반적으로 첫 번째 관심사 여야합니다. 또한 이러한 테스트는 언어 변경 후와 다른 브라우저에서 완전히 의미가 없을 수 있습니다. 응용 프로그램의 속도가 느리다는 것을 알기 위해 프로파일 링해야합니다. 이미 다른 것을 최적화하지 않았다면 정수 나누기 방법이 아닐 것입니다!
JonnyRaa

150

ES6는 새로운 Math.trunc방법을 소개합니다 . 이렇게하면 @MarkElliot의 답변 을 수정 하여 음수에도 사용할 수 있습니다.

var div = Math.trunc(y/x);
var rem = y % x;

Math방법은 비트 연산자에 비해 2 31 이상의 숫자로 작동한다는 점에 유의하십시오 .


var y = 18014398509481984; var x = 5; div =? -버그?
4esn0k

4
@ 4esn0k 버그가 아닙니다. 숫자의 자릿수가 너무 많아 64 비트 이진 형식 IEEE 754 숫자의 정밀도를 가질 수 없습니다. 예를 들면 다음과 같습니다 18014398509481984 == 18014398509481985.
Oriol

18014398509481984 == 2 ** 54이며이 숫자는 정확하게 binary64 형식으로 표시되므로이 숫자를 사용했습니다. 그리고 그 대답은 정확하게 표현되어 있습니다
4esn0k

1
선택은 간단하다고 생각합니다. 최대 32 비트의 부호를 지원해야합니까? 사용하십시오 ~~(x/y). 최대 54 비트의 더 큰 숫자를 지원해야합니까? Math.trunc가지고 있다면 사용하십시오 Math.floor(그렇지 않으면 음수에 맞습니다). 더 큰 숫자를 지원해야합니까? 큰 숫자 라이브러리를 사용하십시오.
Stijn de Witt

4
의 검색에서 구글에서 여기 rubyists을 위해 divmod, 당신은 등을 구현할 수 있습니다function divmod(x, y) { var div = Math.trunc(x/y); var rem = x % y; return [div, rem]; }
알렉스 무어 - 니에미

29
var remainder = x % y;
return (x - remainder) / y;

1
이 버전은 불행히도 x = -100 인 경우 -33 대신 -34를 반환하므로 테스트에 실패합니다.
사무엘

1
"var x = 0.3; var y = 0.01;" ? ( github.com/JuliaLang/julia/issues/4156#issuecomment-23324163 덕분에 )
4esn0k

실제로 음수 값을 갖는 @Samuel은이 메소드가 올바른 결과를 리턴하거나 최소한 Math.trunc:)을 사용하여 메소드와 동일한 값을 리턴합니다 . 100,3으로 확인했습니다. -100,3; 100, -3 및 -100, -3. 물론, 당신의 의견과 사물이 변한 이후 많은 시간이 지났습니다.
Marjan Venema

19

나는 보통 다음을 사용합니다.

const quotient =  (a - a % b) / b;
const remainder = a % b;

아마도 가장 우아하지는 않지만 작동합니다.


1
플로트를 파싱하거나 잘리는 것을 피할 수 있기 때문에 좋은 해결책입니다.
Dem Pilafian 2016 년

6
몫과 나머지가 모두 필요한 경우 나머지를 먼저 계산 한 다음 몫에 대한 표현식에서 해당 값을 다시 사용하십시오 (예 : quotient = (a-나머지) / b;
gb96

2
나머지 = a % b; 몫 = (a-나머지) / b;
Zv_oDD

16

함수 parseInt를 사용하여 잘린 결과를 얻을 수 있습니다.

parseInt(a/b)

나머지를 얻으려면 mod 연산자를 사용하십시오.

a%b

parseInt는 밑줄 10에 기수 매개 변수를 사용하지 않기 위해 문자열에 함정이 있습니다.

parseInt("09", 10)

경우에 따라 숫자의 문자열 표현은 과학적 표기법이 될 수 있으며,이 경우 parseInt는 잘못된 결과를 생성합니다.

parseInt(100000000000000000000000000000000, 10) // 1e+32

이 호출은 결과적으로 1을 생성합니다.


7
parseInt가능하면 피해야합니다. Douglas Crockford의 경고는 다음과 같습니다. "문자열의 첫 문자가 0이면 문자열은 10이 아닌 8 진에서 평가됩니다. 8, 8, 9는 숫자가 아니므로 parseInt ("08 ") 및 parseInt ( "09")는 결과적으로 0을 생성합니다.이 오류는 날짜와 시간을 구문 분석하는 프로그램에서 문제를 발생시킵니다. 다행히도 parseInt는 기수 매개 변수를 사용할 수 있으므로 parseInt ( "08", 10)은 8을 생성합니다. 기수 매개 변수를 제공하십시오. " archive.oreilly.com/pub/a/javascript/excerpts/…
Powers

3
부서에서는 문자열이 아닌 숫자를받을 것으로 예상되지만 이것이 좋은 지적입니다.
에디 포 코스타 Rebouças

2
@Powers는 기수를 추가합니다. 그는 parseInt피해야 한다고 말하지 않았다. 알아야 할 몇 가지 문제가 있습니다. 이러한 것들을 알고 대처할 준비가되어 있어야합니다.
없음

2
parseInt숫자 인수로 전화하지 마십시오 . parseInt숫자를 자르지 않고 부분 숫자 문자열을 구문 분석해야합니다.
Oriol

1
물건이 원래 특정한 방식으로 사용되도록 의도 된 것이 아니라고해서 그렇게해서는 안된다는 의미는 아닙니다. 이 대답은 효과가 있습니다.
fregante

6

JavaScript는 수학적 정의에 따라 음수의 바닥과 정수가 아닌 나머지 수를 계산합니다.

FLOOR는 "매개 변수보다 작은 가장 큰 정수"로 정의됩니다.

  • 양수 : FLOOR (X) = X의 정수 부분;
  • 음수 : FLOOR (X) = X 빼기 1의 정수 부분 (파라미터보다 작아야하므로 더 음수 임)

REMAINDER는 나눗셈의 "남은"(유클리드 산술)로 정의됩니다. 피제수가 정수가 아닌 경우 몫은 일반적으로 정수가 아닙니다. 즉, 나머지가 없지만 몫이 정수가되어야하는 경우 (그리고 누군가가 부동 소수점 숫자), 정수가 아닌 "남은"것입니다.

JavaScript는 모든 것을 예상대로 계산하므로 프로그래머는 올바른 질문을주의해야합니다 (그리고 사람들은 질문에 대답해야합니다!) Yarin의 첫 번째 질문은 "X를 Y로 나누는 정수 나누기"가 아니라, 대신에, "주어진 정수가 다른 정수로가는 횟수". 양수의 경우 정수 나누기 (제수로 나눔)가 숫자 (제수)가 다른 (배수)에 "들어가는"횟수보다 -1 작기 때문에 음수에 대해서는 답이 동일하지만 음수에는 해당되지 않습니다. 즉, FLOOR는 음수의 정수 나누기에 대한 정답을 반환하지만 Yarin은 묻지 않았습니다!

gammax가 올바르게 대답했습니다. 그 코드는 Yarin의 요청에 따라 작동합니다. 다른 한편으로 사무엘은 잘못했거나 수학을하지 않았거나, 그것이 효과가있는 것을 보았을 것입니다. (또한 그는 자신의 모범의 제수는 무엇인지 말하지 않았지만, 그것이 좋기를 바랍니다. 삼):

나머지 = 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 또는 CPU의 FPU에 문제가 있는지 모르겠습니다). 그러나 정수만 포함하는 Yarin의 질문에 대해서는 gammax의 코드가 완벽하게 작동합니다.


5

Math.floor(operation) 연산의 반올림 값을 리턴합니다.

첫 번째 질문의 예 :

var x = 5;
var y = 10.4;
var z = Math.floor(x + y);

console.log(z);

콘솔:

15

번째 질문의 예 :

var x = 14;
var y = 5;
var z = Math.floor(x%y);

console.log(x);

콘솔:

4


2

한 페이지에서 계산할 수있는 페이지 수 : Math.ceil (x / y)


이것이 어떻게 나머지를 제공하는지 알 수 없습니다.
Paul Rooney

1

알렉스 무어-니에미 의 답변 :

에서 Google을 검색하는 Rubyists의 divmod경우 다음과 같이 구현할 수 있습니다.

function divmod(x, y) {
  var div = Math.trunc(x/y);
  var rem = x % y;
  return [div, rem];
}

결과:

// [2, 33]

2
일반적으로 음수가 포함 된 경우 잘린 나눗셈 ( ) 과 다른 divmod바닥 나누기 ( Math.floor)를 사용합니다 Math.trunc. 이것은 NPM divmodpackage , Rubydivmod , SWI-Prologdivmod 및 다른 많은 구현에서도 마찬가지입니다.
Palec

잘린 부서는 바닥 부서보다 ​​자연스럽게 보이는 결과를 제공하지만 호환성은 IMO보다 우선합니다. 바닥 분할을 사용하는 수학 또는 성능상의 이유가있을 수도 있습니다. 일반적으로 divmod두 작업을 개별적으로 계산하는 것보다 두 배 빠르기 때문에 존재합니다. 이러한 성능 이점없이 이러한 기능을 제공하는 것은 혼란 스러울 수 있습니다.
Palec

1

2의 거듭 제곱으로 나누는 경우 비트 연산자를 사용할 수 있습니다.

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)]; }.
Palec

0

삼항을 사용하여 양수 및 음수 값을 처리하는 방법을 결정할 수 있습니다.

var myInt = (y > 0) ? Math.floor(y/x) : Math.floor(y/x) + 1

숫자가 양수이면 모두 정상입니다. 숫자가 음수이면 Math.floor가 음수를 처리하는 방식으로 인해 1이 추가됩니다.


0

이것은 항상 0쪽으로 잘립니다. 너무 늦었는지 확실하지 않지만 여기에 있습니다.

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
    };
}

0

JS 런타임이 그렇게 표현할 수없는 매우 큰 정수의 나머지를 계산해야하는 경우 (2 ^ 32보다 큰 정수는 부동 소수점으로 표시되므로 정밀도가 손실 됨) 약간의 트릭을 수행해야합니다.

이것은 우리 일상의 많은 경우에 존재하는 많은 수의 수표를 확인하는 데 특히 중요합니다 (은행 계좌 번호, 신용 카드 등).

우선 숫자는 문자열로 필요합니다 (그렇지 않으면 이미 정밀도가 떨어지고 나머지는 의미가 없습니다).

str = '123456789123456789123456789'

이제 줄을 더 작은 부분으로 나눠서 나머지 부분과 줄을 연결하면 9 자리가 될 수 있습니다.

digits = 9 - String(divisor).length

문자열을 나눌 정규식 준비

splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g')

예를 들어, digits7이면 정규 표현식은

/.{1,7}(?=(.{7})+$)/g

최대 길이 7의 비어 있지 않은 서브 스트링과 일치합니다.이 문자열 뒤에는 (?=...)7의 배수 인 다수의 문자가옵니다.

이제 각 부분을 정수로 변환하고 나머지를 계산하여 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);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.