[javascript] 자바 스크립트에서 십진수 자르기 (반올림 아님)

십진수를 소수점 이하 자릿수로 자르려고합니다. 이 같은:

5.467   -> 5.46
985.943 -> 985.94

toFixed(2)옳은 일을하지만 가치를 반올림합니다. 값을 반올림 할 필요가 없습니다. 이것이 자바 스크립트에서 가능하기를 바랍니다.



답변

upd :

결국, 반올림 버그는 얼마나 열심히 보상하려고 노력하더라도 항상 당신을 괴롭힐 것입니다. 따라서 문제는 10 진수 표기법으로 정확하게 숫자를 표시하여 공격해야합니다.

Number.prototype.toFixedDown = function(digits) {
    var re = new RegExp("(\\d+\\.\\d{" + digits + "})(\\d)"),
        m = this.toString().match(re);
    return m ? parseFloat(m[1]) : this.valueOf();
};

[   5.467.toFixedDown(2),
    985.943.toFixedDown(2),
    17.56.toFixedDown(2),
    (0).toFixedDown(1),
    1.11.toFixedDown(1) + 22];

// [5.46, 985.94, 17.56, 0, 23.1]

다른 사람들의 컴파일을 기반으로 한 오래된 오류 발생 가능성이있는 솔루션 :

Number.prototype.toFixedDown = function(digits) {
  var n = this - Math.pow(10, -digits)/2;
  n += n / Math.pow(2, 53); // added 1360765523: 17.56.toFixedDown(2) === "17.56"
  return n.toFixed(digits);
}


답변

Dogbert의 대답은 좋지만 코드가 음수를 처리해야 할 경우 Math.floor자체적으로 예기치 않은 결과를 초래할 수 있습니다.

Math.floor(4.3) = 4,하지만Math.floor(-4.3) = -5

일관된 결과를 얻으려면 대신 다음과 같은 도우미 함수를 사용하십시오.

truncateDecimals = function (number) {
    return Math[number < 0 ? 'ceil' : 'floor'](number);
};

// Applied to Dogbert's answer:
var a = 5.467;
var truncated = truncateDecimals(a * 100) / 100; // = 5.46

이 기능의 더 편리한 버전은 다음과 같습니다.

truncateDecimals = function (number, digits) {
    var multiplier = Math.pow(10, digits),
        adjustedNum = number * multiplier,
        truncatedNum = Math[adjustedNum < 0 ? 'ceil' : 'floor'](adjustedNum);

    return truncatedNum / multiplier;
};

// Usage:
var a = 5.467;
var truncated = truncateDecimals(a, 2); // = 5.46

// Negative digits:
var b = 4235.24;
var truncated = truncateDecimals(b, -2); // = 4200

원하는 동작이 아닌 경우 Math.abs첫 번째 줄에에 호출을 삽입합니다 .

var multiplier = Math.pow(10, Math.abs(digits)),

편집 : shendz a = 17.56는 이 솔루션을 사용하면 17.55. 이런 일이 발생하는 이유에 대한 자세한 내용은 모든 컴퓨터 과학자가 부동 소수점 산술에 대해 알아야 할 사항을 참조하십시오 . 불행히도, 모든 부동 소수점 오류 소스를 제거하는 솔루션을 작성하는 것은 자바 스크립트로 매우 까다 롭습니다. 다른 언어에서는 정수 또는 십진수 유형을 사용하지만 자바 스크립트를 사용하면 …

이 솔루션 100 % 정확 해야 하지만 속도도 느려집니다.

function truncateDecimals (num, digits) {
    var numS = num.toString(),
        decPos = numS.indexOf('.'),
        substrLength = decPos == -1 ? numS.length : 1 + decPos + digits,
        trimmedResult = numS.substr(0, substrLength),
        finalResult = isNaN(trimmedResult) ? 0 : trimmedResult;

    return parseFloat(finalResult);
}

속도가 필요하지만 부동 소수점 오류를 피하고 싶다면 BigDecimal.js 와 같은 것을 시도하십시오 . 이 SO 질문에서 다른 javascript BigDecimal 라이브러리를 찾을 수 있습니다. “좋은 Javascript BigDecimal 라이브러리가 있습니까?” Javascript 용 수학 라이브러리에 대한 좋은 블로그 게시물이 있습니다.


답변

var a = 5.467;
var truncated = Math.floor(a * 100) / 100; // = 5.46


답변

toFixed에 대해 0.5를 빼서 반올림을 수정할 수 있습니다.

(f - 0.005).toFixed(2)


답변

고려 이중 물결을 활용 :~~ .

번호를 받아보세요. 를 사용 하여 0 자리까지 자를 수 있도록 소수점 뒤의 유효 자릿수를 곱합니다 ~~. 그 승수를 다시 나눕니다. 이익.

function truncator(numToTruncate, intDecimalPlaces) {
    var numPower = Math.pow(10, intDecimalPlaces); // "numPowerConverter" might be better
    return ~~(numToTruncate * numPower)/numPower;
}

나는 ~~전화를 괄호로 감싸지 않으려 고 노력하고있다 . 작업 순서가 올바르게 작동해야한다고 생각합니다.

alert(truncator(5.1231231, 1)); // is 5.1

alert(truncator(-5.73, 1)); // is -5.7

alert(truncator(-5.73, 0)); // is -5

JSFiddle 링크 .

편집 : 되돌아 보면, 실수로 소수점 왼쪽을 반올림하는 경우도 처리했습니다.

alert(truncator(4343.123, -2)); // gives 4300.

로직은 그 사용법을 찾는 것이 약간 이상하며 빠른 리팩터링의 이점을 누릴 수 있습니다. 하지만 여전히 작동합니다. 좋은 것보다 운이 좋습니다.


답변

좋은 한 줄 솔루션 :

function truncate (num, places) {
  return Math.trunc(num * Math.pow(10, places)) / Math.pow(10, places);
}

그런 다음 다음과 같이 호출하십시오.

truncate(3.5636232, 2); // returns 3.56
truncate(5.4332312, 3); // returns 5.433
truncate(25.463214, 4); // returns 25.4632


답변

|간단하고 잘 작동하기 때문에 사용하여 답변을 던질 것이라고 생각 했습니다.

truncate = function(number, places) {
  var shift = Math.pow(10, places);

  return ((number * shift) | 0) / shift;
};