JavaScript의 모듈로 - 큰 숫자
-
06-09-2019 - |
문제
JS의 모듈로 함수를 사용하여 계산을 시도하지만 올바른 결과(1이어야 함)를 얻지 못합니다.다음은 하드코딩된 코드입니다.
var checkSum = 210501700012345678131468;
alert(checkSum % 97);
Result: 66
여기서 문제는 무엇입니까?
안부, Benedikt
해결책
Benedikt 버전의 개선 사항 : "Crest + = '' + Cdivident;" 버그 픽스입니다. Parseint (Divisor)는 두 인수를 문자열로 전달할 수있게합니다. 결국 빈 문자열을 확인하면 항상 숫자 값을 반환합니다. VAR 명령문이 추가되어 글로벌 변수를 사용하지 않습니다. Foreach를 구식 스타일로 변환하여 이전 JavaScript가있는 브라우저에서 작동합니다. 크레스트를 수정했습니다 == 0; 버그 (감사합니다 @dan.stackoverflow).
function modulo (divident, divisor) { var cDivident = ''; var cRest = ''; for (var i in divident ) { var cChar = divident[i]; var cOperator = cRest + '' + cDivident + '' + cChar; if ( cOperator < parseInt(divisor) ) { cDivident += '' + cChar; } else { cRest = cOperator % divisor; if ( cRest == 0 ) { cRest = ''; } cDivident = ''; } } cRest += '' + cDivident; if (cRest == '') { cRest = 0; } return cRest; }
다른 팁
IBAN 계산의 경우 일반 은행 계좌 번호로 인해 문자열 데이터 유형에 매우 큰 숫자가 포함됩니다.이 큰 숫자에서 97로 나눈 나머지를 찾아야 합니다 -> 큰 숫자 % 97.
데이터 유형을 정수로 변환하자마자 오버플로가 발생하여 음의 정수가 발생하고 결국 잘못된 나머지 값이 발생합니다.(잘못된 결과를 초래하는) 장황한 코드 조각을 보았을 때 나는 내 코드를 공유하지 않을 수 없었습니다.크레딧은 다음으로 이동합니다. 정규수를 사용하여 매우 큰 수의 모듈러스 찾기
modulo: function(divident, divisor) {
var partLength = 10;
while (divident.length > partLength) {
var part = divident.substring(0, partLength);
divident = (part % divisor) + divident.substring(partLength);
}
return divident % divisor;
}
NB여기서는 JavaScript의 최대 정수 위치 15개(및 일부)보다 작기 때문에 10개 위치를 사용합니다. 결과적으로 97보다 큰 숫자가 나오고 근사한 숫자가 됩니다.처음 두 인수가 중요합니다.
당신이 이것에 희생 된 것 같습니다. 정밀도를 잃지 않고 숫자가 갈 수있는 JavaScript의 최고 정수 값은 무엇입니까?
다른 스레드의 내용을 반복하기 위해 :
그것들은 64 비트 플로팅 포인트 값이며, 가장 큰 정확한 적분 값은 2^53입니다. 그러나 사양 섹션에서 [8.5 : 숫자 유형] :
일부 ecmascript 연산자는 포괄적 인 범위 -2^31 ~ 2^31-1 범위 또는 0에서 2^32-1 범위에서 정수 만 처리합니다. 이 연산자는 숫자 유형의 모든 값을 허용하지만 먼저 각 값을 2^32 정수 값 중 하나로 변환합니다. 섹션 0과 0에서 각각 TOINT32 및 TOUINT32 연산자의 설명을 참조하십시오.
그러나 신용이 기한이 어디에 있는지 신용. 지미는 레그 워크 (글쎄, 인터넷 검색)에 대한 대답을 받아 들였다.
마지막으로 내 솔루션 :
function modulo (divident, divisor) {
cDivident = '';
cRest = '';
for each ( var cChar in divident ) {
cOperator = cRest + '' + cDivident + '' + cChar;
if ( cOperator < divisor ) {
cDivident += '' + cChar;
} else {
cRest = cOperator % divisor;
if ( cRest == 0 ) cRest = '';
cDivident = '';
}
}
return cRest;
}
IBANS를 확인하기 위해 ES6에서 작업 (기능적) 솔루션을 복사 및 붙여 넣고 자하는 사람들을 위해 :
function isIBAN(s){
const rearranged = s.substring(4,s.length) + s.substring(0,4);
const numeric = Array.from(rearranged).map(c =>(isNaN(parseInt(c)) ? (c.charCodeAt(0)-55).toString() : c)).join('');
const remainder = Array.from(numeric).map(c => parseInt(c)).reduce((remainder, value) => (remainder * 10 + value) % 97,0);
return remainder === 1;}
당신은 그것을 한 라이너로 쓸 수도 있습니다.
모듈로 작동은 실제 숫자를 저장하는 정수 배열에서 수행됩니다 (divident
, 함수로 문자열로 적용) :
function modulo(divident, divisor){
return Array.from(divident).map(c => parseInt(c)).reduce((remainder, value) => (remainder * 10 + value) % divisor,0);
};
이것은 Modulo가 첨가, 하단 및 곱셈보다 분배되기 때문에 작동합니다.
- (A+B)%M = ((A%M)+(B%M))%M
- (ab)%m = ((a%m)-(b%m))%m
- (ㅏb)%m = ((a%m)(b%m))%m
ES5로 변환 된 IBAN 기능은 다음과 같습니다.
function (s) {
var rearranged = s.substring(4, s.length) + s.substring(0, 4);
var numeric = Array.from(rearranged).map(function (c) { return (isNaN(parseInt(c)) ? (c.charCodeAt(0) - 55).toString() : c); }).join('');
var remainder = Array.from(numeric).map(function (c) { return parseInt(c); }).reduce(function (remainder, value) { return (remainder * 10 + value) % 97; }, 0);
return remainder === 1;
};
Silent Matt는 JavaScript를 개발했습니다 도서관 큰 정수. 이 문제도 해결할 수 있습니다.