문자열이 양의 정수인지 확인


200

JavaScript의 문자열이 양의 정수인지 확인하는 가장 간단한 오류 방지 테스트를 원합니다.

isNaN(str)정수가 아닌 모든 종류의 값에 대해 true를 반환하고 parseInt(str)"2.5"와 같이 부동 문자열에 대한 정수를 반환합니다. 그리고 jQuery 플러그인도 사용하고 싶지 않습니다.


7
"+2"를 허용합니까? "0.1e1"은 어떻습니까? "1.0000"은 어떻습니까?
Phrogz

isNaN()개념 Not a Number은 IEEE 794 부동 소수점 사양에서 매우 특정한 의미를 갖기 때문에 기능이 동작합니다 . 간단한 구어체 질문에 대한 답을 제공하지는 않는다. "이 값은 숫자가 아닌가?"
Pointy

3
문제는 극단적으로 모호하다. "문자열이 정수"인지 확인할 수는 없습니다. 왜냐하면 문자열과 숫자가 동시에있을 수있는 개체가 없기 때문입니다. "문자열이 정수의 유효한 표현인지 테스트하는 방법"을 의미했을 수도 있지만, 이에 대한 답을 구하려면 어떤 언어 나 "문화"를 알고 있는지 알아야합니다. 예를 들어 ٢‎٣٤또는 MCMXIX둘 다 유효한 정수 표현이지만 구문 분석 할 수있는 코드를 찾고 있다고 생각하지 않습니다. 사람들이 혼동하는 것처럼 보이기 때문에 지원할 숫자 형식을 지정할 수 있습니까?
georg

5
나는 '극단으로 모호하다'는 그 자체가 약간 극단적이라고 생각합니다. 어쨌든 ... 문맥은 영어권 국가에서 사용되는 쇼핑 카트의 수량 입력 필드의 유효성을 검사하는 것입니다. "긍정적"이라는 말은 0보다 큼을 의미했습니다. "+2"예, "0.1e1"아니오, "1.000"을 수락 하시겠습니까? 그러나 이러한 다양한 특수 시나리오를 포함 / 제외하도록 조정할 수있는 답변을 제공 할 수 있다면 추가 기능을 제공 할 것이라고 약속합니다 (다른 사람들도 마찬가지입니다).
Mick Byrne

답변:


296

두 가지 답변 :

  • 파싱 ​​기반

  • 정규식

두 경우 모두, 내가 포함 "양의 정수"를 해석 한 것을 참고 0비록은 0긍정적 없습니다. 당신이 허용하지 않으려면 메모를 포함합니다 0.

파싱 ​​기반

합리적인 범위의 값에서 정규화 된 십진 정수 문자열이되도록하려면 다음을 수행하십시오.

function isNormalInteger(str) {
    var n = Math.floor(Number(str));
    return n !== Infinity && String(n) === str && n >= 0;
}

또는 공백과 선행 0을 허용하려는 경우 :

function isNormalInteger(str) {
    str = str.trim();
    if (!str) {
        return false;
    }
    str = str.replace(/^0+/, "") || "0";
    var n = Math.floor(Number(str));
    return n !== Infinity && String(n) === str && n >= 0;
}

라이브 테스트 베드 (앞에 0이나 공백이없는 경우) :

(라이브 테스트 베드 앞의 0과 공백에 대한 처리) :

허용하지 않으려면로 0변경 >= 0하십시오 > 0. (또는 선행 0을 허용하는 버전 || "0"에서는 replace라인을 제거하십시오 .)

작동 방식 :

  1. 공백과 선행 0을 허용하는 버전에서 :

    • str = str.trim(); 앞뒤 공백을 제거합니다.
    • if (!str) 빈 문자열을 잡아서 나머지 작업을 수행 할 때 아무런 의미가 없습니다.
    • str = str.replace(/^0+/, "") || "0"; 문자열에서 모든 선행 0을 제거합니다. 그러나 빈 문자열이되면 단일 0을 복원합니다.
  2. Number(str): str숫자로 변환 ; 그 수는 소수 부분을 가질 수 있거나 또는 일 수있다 NaN.

  3. Math.floor: 숫자를 자릅니다 (소수 부분 잘라 냄).

  4. String(...): 결과를 다시 정상 10 진수 문자열로 변환합니다. 실제로 큰 숫자의 경우 과학 표기법으로 이동 하여이 접근법을 깨뜨릴 수 있습니다. (스 플리트가 어디에 있는지, 세부 사항이 spec에 있는지 잘 모르겠지만 , 전체 숫자의 경우 IEEE-754와 같이 21 자리를 초과 한 시점에 있다고 생각합니다. 배정도 숫자는 대략 15 자리의 정밀도 만 갖습니다.)

  5. ... === str: 원래 문자열과 비교합니다.

  6. n >= 0: 긍정적인지 확인하십시오.

이것은 "+1"입력에서, 과학적 표기법의 입력에서 String(...)스테이지 에서 동일한 과학적 표기법으로 다시 돌아 가지 않으며 JavaScript가 사용하는 숫자 종류 (IEEE-754 배정도 이진 부동 소수점)에 대해서는 실패합니다. 주어진 구문과 다른 값에 더 가까운 구문을 정확하게 나타낼 수 없습니다 (예를 들어, 9,007,199,254,740,992 이상의 많은 정수 포함; 1234567890123456789실패). 전자는 쉬운 해결책이며, 후자는 그다지 많지 않습니다.

정규식

다른 접근 방식은 정규 표현식을 통해 문자열의 문자를 테스트하는 것입니다. 목표는 옵션 +다음 0에 일반 10 진수 형식의 문자열을 허용하는 것입니다 (예 :).

function isNormalInteger(str) {
    return /^\+?(0|[1-9]\d*)$/.test(str);
}

라이브 테스트 베드 :

작동 방식 :

  1. ^: 문자열의 일치 시작

  2. \+?: 단일 옵션을 허용합니다 +(원치 않는 경우 제거)

  3. (?:...|...): 캡처 그룹을 작성하지 않고 다음 두 옵션 중 하나를 허용하십시오.

    1. (0|...): 0스스로 허용 ...

    2. (...|[1-9]\d*): ... 또는 010 진수 이외의 숫자로 시작하는 숫자.

  4. $: 문자열 끝과 일치합니다.

0긍정적이지 않기 때문에 허용하지 않으려면 정규 표현식이 그대로됩니다 /^\+?[1-9]\d*$/(예 : 허용해야하는 대체 항목을 잃을 수 있음 0).

당신이 선행 0 (0123, 00524)을 허용 할 경우, 바로 교대 교체 (?:0|[1-9]\d*)로를\d+

function isNormalInteger(str) {
    return /^\+?\d+$/.test(str);
}

공백을 허용하려면 \s*직후 ^\s*바로 앞에 추가하십시오 $.

당신이 수 있음을 변환 할 때 참고 : 현대 엔진에 아마 사용하기에 괜찮을 것 +str또는 Number(str)그것을 할 수 있지만, 오래된 것들 앞에 0 수단을 말한다 비표준 (하지만 이전-허용) 방식으로 사람들을 확장 할 수있는 8 진수 (base 8), 예를 들어 "010"=> 8. 숫자의 유효성을 검사 한 후에는 parseInt(str, 10)10 진수 (base 10)로 구문 분석되도록 안전하게 사용할 수 있습니다 . parseInt문자열 끝에 가비지를 무시하지만 정규 표현식에 아무것도 없는지 확인했습니다.


모두 Number(' ')Number('')복귀 0하면서 반환해야합니다 NaN대신.
neurino

@ TJCrowder ok 그러나 어떻게 든 거부하려면 ''2a ''와 같은 문자열 이 필요parseInt 합니다 2.
neurino

@neurino : /\D/.test('2a')숫자가 아니기 때문에 true입니다. 아마 if (!/\D/.test(str) && !isNan((num = parseInt(str, 10))) { /* Valid number in num */}... 내 머리 꼭대기에서 ...
TJ Crowder

성능면에서 어떤 방법이 더 빠를까요? 아니면 어느 것이 좋습니다?
phkavitha

@phkavitha : JavaScript 성능 질문에 대한 답변은 엔진마다 서로 다르기 때문에 거의 항상 "의존"입니다. jsperf.com을 사용하여 대상 엔진 / 브라우저를 테스트 할 수 있습니다 . 나는이 작업이 주어진 응용 프로그램에서 병목 현상이 될 것이라고 생각하지 않을 것입니다 ... :-)
TJ Crowder

76

해결책 1

우리가 경우 고려 최대의 값으로 자바 스크립트 정수 4294967295(예 Math.pow(2,32)-1), 다음 짧은 솔루션은 완벽하게 작업을 것입니다 :

function isPositiveInteger(n) {
    return n >>> 0 === parseFloat(n);
}

기술:

  1. 제로 채우기 오른쪽 시프트 연산자 는 세 가지 중요한 작업을 수행합니다.
    • 소수점 이하 자르기
      • 123.45 >>> 0 === 123
    • 음수 이동
      • -1 >>> 0 === 4294967295
    • 의 범위에서 "작동" MAX_INT
      • 1e10 >>> 0 === 1410065408
      • 1e7 >>> 0 === 10000000
  2. parseFloat문자열 번호를 올바르게 구문 분석합니다 ( NaN숫자가 아닌 문자열에 대한 설정 ).

테스트 :

"0"                     : true
"23"                    : true
"-10"                   : false
"10.30"                 : false
"-40.1"                 : false
"string"                : false
"1234567890"            : true
"129000098131766699.1"  : false
"-1e7"                  : false
"1e7"                   : true
"1e10"                  : false
"1edf"                  : false
" "                     : false
""                      : false

데모 : http://jsfiddle.net/5UCy4/37/


해결책 2

또 다른 방법은 Number.MAX_VALUE, 최대 약 유효한 모든 숫자 값에 적합합니다 1.7976931348623157e+308.

function isPositiveInteger(n) {
    return 0 === n % (!isNaN(parseFloat(n)) && 0 <= ~~n);
}

기술:

  1. !isNaN(parseFloat(n))필터링하는 데 사용되는 순수 문자열 값을, 예를 들어 "", " ", "string",
  2. 0 <= ~~n네거티브 크고 정수가 아닌 값을, 예를 들면 필터 "-40.1", "129000098131766699";
  3. (!isNaN(parseFloat(n)) && 0 <= ~~n)true값이 숫자 이고 양수인 경우를 반환 합니다 .
  4. 0 === n % (...)값이 아닌 경우 플로트 체크 - 여기에서 (...)(3 참조)와 같은 평가 0의 경우 false와 같은 1경우 true.

테스트 :

"0"                     : true
"23"                    : true
"-10"                   : false
"10.30"                 : false
"-40.1"                 : false
"string"                : false
"1234567890"            : true
"129000098131766699.1"  : false
"-1e10"                 : false
"1e10"                  : true
"1edf"                  : false
" "                     : false
""                      : false

데모 : http://jsfiddle.net/5UCy4/14/


이전 버전 :

function isPositiveInteger(n) {
    return n == "0" || ((n | 0) > 0 && n % 1 == 0);
}

데모 : http://jsfiddle.net/5UCy4/2/


빈 문자열 또는 1290000981231123.1과 같은 큰 숫자를 사용해보십시오. jsfiddle.net/5UCy4/1
Niko

@gdoron ~~val분수 부분을 잘라내는 것과 같습니다 . 두 개가 아닌 하나의 비트 단위 연산을 수행하기 때문에 조금 더 빠릅니다.
VisioN 2016 년

좋은 대답입니다. 개인적으로 나는 가독성을 위해 좀 더 장황한 것을 선호합니다(!isNaN(parseFloat(n)) && n % 1 === 0 && 0 <= ~~n)
Ramy Nasr

true, false, 0xFF및 다른 값 isPositiveInteger은 감지되지 않고 통과 합니다.
Xeoncross

1
이것은 심지어 채워진 0을 처리합니다 (좋은!). 테스트에 추가 할 수 있습니다.
Rashack

21

정규 표현식이가는 방법 인 것 같습니다.

var isInt = /^\+?\d+$/.test('the string');

"1.0"또는 ".1e1"이 허용되지 않는 한 닫습니다.
Phrogz

Well 1290000192379182379123782900192981231은 정수이지만 JavaScript 네이티브 숫자로 정확하게 표현할 수 없으므로 정규 표현식을 사용하면 숫자 변환을 수행하고 작동하는지 확인해야합니다.
Pointy

이것은 매우 부정확 한 솔루션입니다.
usr

@ usr : 0일반적으로 기대하지 않는 곳을 이끌 수 있다고 생각 하지만, 대부분 괜찮습니다.
TJ Crowder

범위가 최대 2 ^ 31-1인지 확인하지 않으며 아라비아 숫자를 허용하지 않습니다. 이것은 좋은 해결책이 아닌 해킹입니다. 가장 좋은 해결책은이 질문에 가장 찬성입니다. 왜 사용하지 않습니까? 모든면에서 더 좋습니다.
usr

17

노드 및 모든 브라우저 (IE 및 Opera Mini 제외) 의 90 % 이상 에서 작동하는 최신 솔루션은 Number.isInteger 를 사용 하고 간단한 긍정적 인 확인을 수행하는 것입니다.

Number.isInteger(x) && x > 0

이것은 ECMAScript 2015에서 마무리되었습니다 .

function isPositiveInteger(x) {
    return Number.isInteger(x) && x > 0
}

Polyfil은 다음과 같습니다.

Number.isInteger = Number.isInteger || function(value) {
  return typeof value === 'number' && 
    isFinite(value) && 
    Math.floor(value) === value;
};

문자열 로 된 입력을 지원해야하는 경우 또는 숫자 형식의 경우이 기능을 사용할있습니다.이 기능은 모든 기존 답변 (2018 년 2 월 1 일)이 특정 형식의 입력에서 실패한 후 대규모 테스트 스위트를 작성했습니다.

function isPositiveInteger(v) {
  var i;
  return v && (i = parseInt(v)) && i > 0 && (i === v || ''+i === v);
}

4

이것은 이것에 대한 거의 중복 질문입니다.

JavaScript에서 10 진수 유효성 검사-IsNumeric ()

대답은 다음과 같습니다.

function isNumber(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

따라서 양의 정수는 다음과 같습니다.

function isPositiveInteger(n) {
  var floatN = parseFloat(n);
  return !isNaN(floatN) && isFinite(n) && floatN > 0
      && floatN % 1 == 0;
}

나는 그것이 'JavaScript의 유효한 숫자'질문과 거의 동일하다는 것을 알고, 그 모든 것을 읽었지만 정수의 문자열 표현에 대한 질문은 자신의 페이지에 가치가 있다고 생각했습니다.
Mick Byrne

2
return ((parseInt(str, 10).toString() == str) && str.indexOf('-') === -1);

'0001'과 같은 문자열을 제공하면 작동하지 않습니다.


2

내 함수는 숫자가 + ve인지 확인하고 십진수 값을 가질 수도 있습니다.

       function validateNumeric(numValue){
            var value = parseFloat(numValue);
            if (!numValue.toString().match(/^[-]?\d*\.?\d*$/)) 
                    return false;
            else if (numValue < 0) {
                return false;
            }
            return true;        
        }

2

위의 VisioN의 답변을 바탕으로 jQuery 유효성 검사 플러그인을 사용하는 경우 다음을 사용할 수 있습니다.

$(document).ready(function() {
    $.validator.addMethod('integer', function(value, element, param) {
        return (value >>> 0 === parseFloat(value) && value > 0);
    }, 'Please enter a non zero integer value!');
}

그런 다음 일반 규칙 세트에서 사용하거나 다음과 같이 동적으로 추가 할 수 있습니다.

$("#positiveIntegerField").rules("add", {required:true, integer:true});

2

단순한

function isInteger(num) {
  return (num ^ 0) === num;
}

console.log(isInteger(1));

또한 프로토 타입을 통해 Number를 확장하고 함수를 할당 할 수도 있습니다.


1

HTML5 양식을 사용하는 min="0"경우 form element에 attribute 를 사용할 수 있습니다 <input type="number" />. 이것은 모든 주요 브라우저에서 지원됩니다. 이러한 간단한 작업에는 Javascript가 포함되어 있지 않지만 새로운 HTML 표준에 통합되어 있습니다. https://www.w3schools.com/tags/att_input_min.asp에 설명되어 있습니다.


0

(~~a == a)a문자열은 어디에 있습니까 ?


1
음수에 대해서는 실패합니다 : ~~"-1" == "-1"를 반환 true합니다. 그리고 OP는 양의 정수만을 요구했습니다.
Igor Milla 2016 년

1
''및 ''에도 실패합니다.
neverfox

0

ES6 :

Number.isInteger(Number(theNumberString)) > 0
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.