programing

필요한 경우 소수점 이하 2자리까지 반올림하는 방법

goodsources 2023. 2. 6. 23:27
반응형

필요한 경우 소수점 이하 2자리까지 반올림하는 방법

소수점 이하 두 자리까지 반올림하고 싶은데, 꼭 필요한 경우만요.

입력:

10
1.7777777
9.1

출력:

10
1.78
9.1

JavaScript에서 이 작업을 수행하려면 어떻게 해야 합니까?

사용방법:

Math.round(num * 100) / 100

또는 보다 구체적으로 1.005 라운드와 같은 것을 올바르게 하려면 번호를 사용합니다.EPSILON:

Math.round((num + Number.EPSILON) * 100) / 100

값이 텍스트 유형인 경우:

parseFloat("123.456").toFixed(2);

값이 숫자일 경우:

var numb = 123.23454;
numb = numb.toFixed(2);

1.5와 같은 값이 출력으로 "1.50"이 된다는 단점이 있습니다.@minitech가 제안하는 수정:

var numb = 1.5;
numb = +numb.toFixed(2);
// Note the plus sign that drops any "extra" zeroes at the end.
// It changes the result (which is a string) into a number again (think "0 + foo"),
// which means that it uses only as many digits as necessary.

것 같다Math.round더 나은 해결책입니다.하지만 그렇지 않아요!경우에 따라서는 올바르게 반올림되지 않을 수 있습니다.

Math.round(1.005 * 100)/100 // Returns 1 instead of expected 1.01!

또한 경우에 따라서는 toFixed()가 올바르게 반올림되지 않습니다(Chrome v.55.0.2883.87에서 테스트됨).

예:

parseFloat("1.555").toFixed(2); // Returns 1.55 instead of 1.56.
parseFloat("1.5550").toFixed(2); // Returns 1.55 instead of 1.56.
// However, it will return correct result if you round 1.5551.
parseFloat("1.5551").toFixed(2); // Returns 1.56 as expected.

1.3555.toFixed(3) // Returns 1.355 instead of expected 1.356.
// However, it will return correct result if you round 1.35551.
1.35551.toFixed(2); // Returns 1.36 as expected.

1.555가 실제로는 1.554994가 뒤에서 뜨는 것과 같기 때문인 것 같아요.

솔루션 1은 다음과 같이 필요한 반올림 알고리즘이 있는 스크립트를 사용하는 것입니다.

function roundNumber(num, scale) {
  if(!("" + num).includes("e")) {
    return +(Math.round(num + "e+" + scale)  + "e-" + scale);
  } else {
    var arr = ("" + num).split("e");
    var sig = ""
    if(+arr[1] + scale > 0) {
      sig = "+";
    }
    return +(Math.round(+arr[0] + "e" + sig + (+arr[1] + scale)) + "e-" + scale);
  }
}

그것은 또한 플런커에 있다.

주의: 이 솔루션은 모든 사용자에게 범용적인 솔루션은 아닙니다.몇 가지 다른 반올림 알고리즘이 있습니다.실장은 요건에 따라 다를 수 있습니다.반올림을 참조하십시오.

솔루션 2는 프런트 엔드의 계산을 피하고 백엔드 서버에서 반올림된 값을 추출하는 것입니다.

또 다른 가능한 해결책은 방탄도 아니다.

Math.round((num + Number.EPSILON) * 100) / 100

1.354999999999998과 같은 숫자를 반올림하면 잘못된 결과가 반환될 수 있습니다.1.35여야 하는데 결과는 1.36입니다.

사용할 수 있습니다.

function roundToTwo(num) {
    return +(Math.round(num + "e+2")  + "e-2");
}

MDN에서 찾았습니다.그들의 방법은 언급된 1.005의 문제를 회피할 수 있습니다.

roundToTwo(1.005)
1.01
roundToTwo(10)
10
roundToTwo(1.7777777)
1.78
roundToTwo(9.1)
9.1
roundToTwo(1234.5678)
1234.57

MarkG 정답입니다.여기 소수점 이하에 대한 일반 확장자가 있습니다.

Number.prototype.round = function(places) {
  return +(Math.round(this + "e+" + places)  + "e-" + places);
}

사용방법:

var n = 1.7777;    
n.round(2); // 1.78

유닛 테스트:

it.only('should round floats to 2 places', function() {
    
  var cases = [
    { n: 10,      e: 10,    p:2 },
    { n: 1.7777,  e: 1.78,  p:2 },
    { n: 1.005,   e: 1.01,  p:2 },
    { n: 1.005,   e: 1,     p:0 },
    { n: 1.77777, e: 1.8,   p:1 }
  ]
    
  cases.forEach(function(testCase) {
    var r = testCase.n.round(testCase.p);
    assert.equal(r, testCase.e, 'didn\'t get right number');
  });
})

다음을 사용해야 합니다.

Math.round( num * 100 + Number.EPSILON ) / 100

아무도 모르는 것 같다.

또한 이것은 일부 사람들이 말한 처럼 JavaScript의 이상함이 아니라는 것을 주목할 필요가 있다.

이것은 단순히 컴퓨터에서 부동 소수점 숫자가 작동하는 방식이다.프로그래밍 언어의 99%와 마찬가지로 JavaScript에는 홈메이드 부동소수점 숫자가 없습니다. 이를 위해 CPU/FPU에 의존합니다.컴퓨터는 2진수를 사용하고, 2진수에는 다음과 같은 숫자가 없습니다.0.12번, 2번이요?1쓸수은 0.1/3입니다. 0.33333333...무한히 세 개로.

자, 이리 와.이 숫자는 배정도 부동소수점 숫자에 존재하는 1과 다음 숫자의 차이입니다.이상입니다. ~ 1 + 사이에는 숫자를 사용할 수 없습니다.

편집:

처럼 한 요.추가Number.EPSILON는 반올림할 값이 산술 연산의 결과일 경우에만 관련이 있습니다.이는 부동소수점 오차 델타를 삼킬 수 있기 때문입니다.

값이 직접 소스(예: 리터럴, 사용자 입력 또는 센서)에서 나오는 경우에는 유용하지 않습니다.

편집(2019):

@maganap과 일부 사람들이 지적한 것처럼 곱하기 전에 추가하는 것이 가장 좋습니다.

Math.round( ( num + Number.EPSILON ) * 100 ) / 100

편집(2019년 12월):

최근에는 다음과 같은 기능을 사용하여 엡실론 인식 숫자를 비교하고 있습니다.

const ESPILON_RATE = 1 + Number.EPSILON ;
const ESPILON_ZERO = Number.MIN_VALUE ;

function epsilonEquals( a , b ) {
  if ( Number.isNaN( a ) || Number.isNaN( b ) ) {
    return false ;
  }
  if ( a === 0 || b === 0 ) {
    return a <= b + EPSILON_ZERO && b <= a + EPSILON_ZERO ;
  }
  return a <= b * EPSILON_RATE && b <= a * EPSILON_RATE ;
}

저의 유스케이스는 수년간 개발하고 있는 어설션 + 데이터 검증 lib입니다.

제가 하고 있는 에서는, ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」ESPILON_RATE = 1 + 4 * Number.EPSILON ★★★★★★★★★★★★★★★★★」EPSILON_ZERO = 4 * Number.MIN_VALUE(엡실론의 4배) 부동소수점 오차를 누적하기 위해 충분히 느슨한 등식 체커를 원하기 때문입니다.

지금까지는 완벽해 보여요.도움이 되었으면 좋겠어요.

스케일링으로 .round(num * p) / p

간단한 구현

중간값과 함께 다음 함수를 사용하면 예상대로 반올림된 상한 값 또는 입력에 따라 반올림된 하한 값을 얻을 수 있습니다.

★★★★★★★★★★★★★★★★★.inconsistency반올림 시 클라이언트 코드의 버그를 검출하기 어려운 경우가 있습니다.

function naiveRound(num, decimalPlaces = 0) {
    var p = Math.pow(10, decimalPlaces);
    return Math.round(num * p) / p;
}

console.log( naiveRound(1.245, 2) );  // 1.25 correct (rounded as expected)
console.log( naiveRound(1.255, 2) );  // 1.25 incorrect (should be 1.26)

// testing edge cases
console.log( naiveRound(1.005, 2) );  // 1    incorrect (should be 1.01)
console.log( naiveRound(2.175, 2) );  // 2.17 incorrect (should be 2.18)
console.log( naiveRound(5.015, 2) );  // 5.01 incorrect (should be 5.02)

반올림 연산에 중간점 값이 포함되는지 여부를 판단하기 위해 반올림 함수는 원래 값에 10**n을 곱하고 여기서 n은 반환값의 원하는 소수 자릿수이며, 그 값의 나머지 소수 부분이 0.5보다 큰지 또는 같은지를 판단한다. ★★★★★★★★★★★★★★★★★."Exact Testing for Equality"부동소수점 형식의 바이너리 표현 및 정밀도 문제로 인해 부동소수점 값이 있으면 문제가 발생합니다. 0.약간 은 위로.

예에서는 " " " 입니다.5.015 이하 시 5.은 5.015*100입니다.501.49999999999994 . 보다 작기 으로 5. . 499999999994 .5이다.

구현의 향상

지수 표기법

이 수를 지수 표기 문자열로 변환하면 양의 숫자는 예상대로 반올림됩니다.단, 음수는 양수와 다르게 반올림한다는 점에 유의하시기 바랍니다.

실제로 기본적으로 "반올림"과 동등한 기능을 수행합니다.round(-1.005, 2)-1round(1.005, 2)1.01. lodash _.round 메서드는 이 기술을 사용합니다.

/**
 * Round half up ('round half towards positive infinity')
 * Negative numbers round differently than positive numbers.
 */
function round(num, decimalPlaces = 0) {
    num = Math.round(num + "e" + decimalPlaces);
    return Number(num + "e" + -decimalPlaces);
}

// test rounding of half
console.log( round(0.5) );  // 1
console.log( round(-0.5) ); // 0

// testing edge cases
console.log( round(1.005, 2) );   // 1.01
console.log( round(2.175, 2) );   // 2.18
console.log( round(5.015, 2) );   // 5.02

console.log( round(-1.005, 2) );  // -1
console.log( round(-2.175, 2) );  // -2.17
console.log( round(-5.015, 2) );  // -5.01

음수를 반올림할 때 일반적인 동작을 원할 경우 Math.round()를 호출하기 전에 음수를 양수로 변환한 다음 반환하기 전에 음수로 다시 변환해야 합니다.

// Round half away from zero
function round(num, decimalPlaces = 0) {
    if (num < 0)
        return -round(-num, decimalPlaces);

    num = Math.round(num + "e" + decimalPlaces);
    return Number(num + "e" + -decimalPlaces);
}

대략적인 반올림

naiveRound예를 들어, 우리는 분수 값이 중간점 반올림 대상이 될 만큼 중간점 값에 충분히 가까운지 여부를 결정하기 위해 "균등" 테스트를 수행하는 사용자 정의 반올림 함수를 정의할 수 있다.

// round half away from zero
function round(num, decimalPlaces = 0) {
    if (num < 0)
        return -round(-num, decimalPlaces);
    var p = Math.pow(10, decimalPlaces);
    var n = num * p;
    var f = n - Math.floor(n);
    var e = Number.EPSILON * n;

    // Determine whether this fraction is a midpoint value.
    return (f >= .5 - e) ? Math.ceil(n) / p : Math.floor(n) / p;
}

// test rounding of half
console.log( round(0.5) );  // 1
console.log( round(-0.5) ); // -1

// testing edge cases
console.log( round(1.005, 2) );  // 1.01
console.log( round(2.175, 2) );  // 2.18
console.log( round(5.015, 2) );  // 5.02

console.log( round(-1.005, 2) ); // -1.01
console.log( round(-2.175, 2) ); // -2.18
console.log( round(-5.015, 2) ); // -5.02

Number.EPSILON

반올림 함수를 호출하기 전에 엡실론 보정이 적용되는 라운드 투 근접('0에서 반올림 반' 사용)을 수행하는 다른 순수 수학 기법이 있습니다.

반올림 전 제품에 가능한 한 작은 부동값(= 1.0 ulp, 꼴찌 단위)을 더하면 됩니다.이는 0에서 떨어진 다음 표시 가능한 부동값으로 이동하며, 따라서 곱셈 중에 발생할 수 있는 이진 반올림 오류를 다음으로 상쇄합니다.10 ** n.

/**
 * Round half away from zero ('commercial' rounding)
 * Uses correction to offset floating-point inaccuracies.
 * Works symmetrically for positive and negative numbers.
 */
function round(num, decimalPlaces = 0) {
    var p = Math.pow(10, decimalPlaces);
    var n = (num * p) * (1 + Number.EPSILON);
    return Math.round(n) / p;
}

// rounding of half
console.log( round(0.5) );  // 1
console.log( round(-0.5) ); // -1

// testing edge cases
console.log( round(1.005, 2) );  // 1.01
console.log( round(2.175, 2) );  // 2.18
console.log( round(5.015, 2) );  // 5.02

console.log( round(-1.005, 2) ); // -1.01
console.log( round(-2.175, 2) ); // -2.18
console.log( round(-5.015, 2) ); // -5.02

ulp를 5의 이 1 ulp입니다.501.49999999999994 부분은 '고치다'로 정정됩니다.501.50000000000006이 값은 502로 반올림되어 최종적으로 5.02가 됩니다.

꼴찌 단위 크기("ulp")는 (1) 숫자의 크기와 (2) 상대 기계 엡실론(2^-52)에 의해 결정됩니다.울프는 크기가 작은 숫자에 비해 크기가 큰 숫자에 비해 상대적으로 크다.

더블 라운딩

여기에서는 toPrecision() 메서드를 사용하여 중간 계산에서 부동 소수점 반올림 오류를 제거합니다.단순히 유효 자리수 15자리를 반올림하여 16번째 유효 자리수의 반올림 오류를 제거합니다.결과를 유효 자릿수로 사전 반올림하는 이 기술은 PHP 7 라운드 함수에서도 사용됩니다.

* 값 5.015 * 100 은 。501.49999999999994합니다.501.500000000000그 후 502로 반올림하여 최종적으로 5.02가 됩니다.

// Round half away from zero
function round(num, decimalPlaces = 0) {
    if (num < 0)
        return -round(-num, decimalPlaces);
    var p = Math.pow(10, decimalPlaces);
    var n = (num * p).toPrecision(15);
    return Math.round(n) / p;
}

// rounding of half
console.log( round(0.5) );  // 1
console.log( round(-0.5) ); // -1

// testing edge cases
console.log( round(1.005, 2) );  // 1.01
console.log( round(2.175, 2) );  // 2.18
console.log( round(5.015, 2) );  // 5.02

console.log( round(-1.005, 2) ); // -1.01
console.log( round(-2.175, 2) ); // -2.18
console.log( round(-5.015, 2) ); // -5.02

임의 정밀도 JavaScript 라이브러리 - 10진수.js

// Round half away from zero
function round(num, decimalPlaces = 0) {
    return new Decimal(num).toDecimalPlaces(decimalPlaces).toNumber();
}

// rounding of half
console.log( round(0.5) );  // 1
console.log( round(-0.5) ); // -1

// testing edge cases
console.log( round(1.005, 2) );  // 1.01
console.log( round(2.175, 2) );  // 2.18
console.log( round(5.015, 2) );  // 5.02

console.log( round(-1.005, 2) ); // -1.01
console.log( round(-2.175, 2) ); // -2.18
console.log( round(-5.015, 2) ); // -5.02
<script src="https://cdnjs.cloudflare.com/ajax/libs/decimal.js/10.2.1/decimal.js" integrity="sha512-GKse2KVGCCMVBn4riigHjXE8j5hCxYLPXDw8AvcjUtrt+a9TbZFtIKGdArXwYOlZvdmkhQLWQ46ZE3Q1RIa7uQ==" crossorigin="anonymous"></script>

해결책 1: 지수 표기 문자열

KFish가 제공하는 솔루션에서 영감을 얻어 다음 사이트를 방문하십시오.https://stackoverflow.com/a/55521592/4208440

전체 라이브러리를 추가하지 않고도 소수점 이하 자리수까지 정확한 소수점 반올림, 바닥재 및 천장을 제공하는 단순한 솔루션 드롭입니다.예기치 않은 결과를 피하기 위해 2진수 반올림 문제를 수정함으로써 플로트를 소수점처럼 취급합니다.예를 들어 floor((0.1+0.7)*10)는 예상된 결과 8을 반환합니다.

숫자는 특정 소수 자릿수로 반올림됩니다.음의 정밀도를 지정하면 소수점 왼쪽의 임의의 자리수로 반올림됩니다.

// Solution 1
var DecimalPrecision = (function() {
    if (Math.trunc === undefined) {
        Math.trunc = function(v) {
            return v < 0 ? Math.ceil(v) : Math.floor(v);
        };
    }
    var decimalAdjust = function myself(type, num, decimalPlaces) {
        if (type === 'round' && num < 0)
            return -myself(type, -num, decimalPlaces);
        var shift = function(value, exponent) {
            value = (value + 'e').split('e');
            return +(value[0] + 'e' + (+value[1] + (exponent || 0)));
        };
        var n = shift(num, +decimalPlaces);
        return shift(Math[type](n), -decimalPlaces);
    };
    return {
        // Decimal round (half away from zero)
        round: function(num, decimalPlaces) {
            return decimalAdjust('round', num, decimalPlaces);
        },
        // Decimal ceil
        ceil: function(num, decimalPlaces) {
            return decimalAdjust('ceil', num, decimalPlaces);
        },
        // Decimal floor
        floor: function(num, decimalPlaces) {
            return decimalAdjust('floor', num, decimalPlaces);
        },
        // Decimal trunc
        trunc: function(num, decimalPlaces) {
            return decimalAdjust('trunc', num, decimalPlaces);
        },
        // Format using fixed-point notation
        toFixed: function(num, decimalPlaces) {
            return decimalAdjust('round', num, decimalPlaces).toFixed(decimalPlaces);
        }
    };
})();

// test rounding of half
console.log(DecimalPrecision.round(0.5));  // 1
console.log(DecimalPrecision.round(-0.5)); // -1

// testing very small numbers
console.log(DecimalPrecision.ceil(1e-8, 2) === 0.01);
console.log(DecimalPrecision.floor(1e-8, 2) === 0);

// testing simple cases
console.log(DecimalPrecision.round(5.12, 1) === 5.1);
console.log(DecimalPrecision.round(-5.12, 1) === -5.1);
console.log(DecimalPrecision.ceil(5.12, 1) === 5.2);
console.log(DecimalPrecision.ceil(-5.12, 1) === -5.1);
console.log(DecimalPrecision.floor(5.12, 1) === 5.1);
console.log(DecimalPrecision.floor(-5.12, 1) === -5.2);
console.log(DecimalPrecision.trunc(5.12, 1) === 5.1);
console.log(DecimalPrecision.trunc(-5.12, 1) === -5.1);

// testing edge cases for round
console.log(DecimalPrecision.round(1.005, 2) === 1.01);
console.log(DecimalPrecision.round(39.425, 2) === 39.43);
console.log(DecimalPrecision.round(-1.005, 2) === -1.01);
console.log(DecimalPrecision.round(-39.425, 2) === -39.43);

// testing edge cases for ceil
console.log(DecimalPrecision.ceil(9.13, 2) === 9.13);
console.log(DecimalPrecision.ceil(65.18, 2) === 65.18);
console.log(DecimalPrecision.ceil(-2.26, 2) === -2.26);
console.log(DecimalPrecision.ceil(-18.15, 2) === -18.15);

// testing edge cases for floor
console.log(DecimalPrecision.floor(2.26, 2) === 2.26);
console.log(DecimalPrecision.floor(18.15, 2) === 18.15);
console.log(DecimalPrecision.floor(-9.13, 2) === -9.13);
console.log(DecimalPrecision.floor(-65.18, 2) === -65.18);

// testing edge cases for trunc
console.log(DecimalPrecision.trunc(2.26, 2) === 2.26);
console.log(DecimalPrecision.trunc(18.15, 2) === 18.15);
console.log(DecimalPrecision.trunc(-2.26, 2) === -2.26);
console.log(DecimalPrecision.trunc(-18.15, 2) === -18.15);

// testing round to tens and hundreds
console.log(DecimalPrecision.round(1262.48, -1) === 1260);
console.log(DecimalPrecision.round(1262.48, -2) === 1300);

// testing toFixed()
console.log(DecimalPrecision.toFixed(1.005, 2) === "1.01");

해결책 2: 순수하게 수학적인 (숫자)EPSILON)

이 솔루션은 성능상의 이유로 문자열 변환이나 조작을 회피합니다.

// Solution 2
var DecimalPrecision2 = (function() {
    if (Number.EPSILON === undefined) {
        Number.EPSILON = Math.pow(2, -52);
    }
    if (Math.trunc === undefined) {
        Math.trunc = function(v) {
            return v < 0 ? Math.ceil(v) : Math.floor(v);
        };
    }
    var powers = [
        1e0,  1e1,  1e2,  1e3,  1e4,  1e5,  1e6,  1e7,
        1e8,  1e9,  1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
        1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22
    ];
    var intpow10 = function(power) {
        if (power < 0 || power > 22) {
            return Math.pow(10, power);
        }
        return powers[power];
    };
    var isRound = function(num, decimalPlaces) {
        //return decimalPlaces >= 0 &&
        //    +num.toFixed(decimalPlaces) === num;
        var p = intpow10(decimalPlaces);
        return Math.round(num * p) / p === num;
    };
    var decimalAdjust = function(type, num, decimalPlaces) {
        if (type !== 'round' && isRound(num, decimalPlaces || 0))
            return num;
        var p = intpow10(decimalPlaces || 0);
        var n = (num * p) * (1 + Number.EPSILON);
        return Math[type](n) / p;
    };
    return {
        // Decimal round (half away from zero)
        round: function(num, decimalPlaces) {
            return decimalAdjust('round', num, decimalPlaces);
        },
        // Decimal ceil
        ceil: function(num, decimalPlaces) {
            return decimalAdjust('ceil', num, decimalPlaces);
        },
        // Decimal floor
        floor: function(num, decimalPlaces) {
            return decimalAdjust('floor', num, decimalPlaces);
        },
        // Decimal trunc
        trunc: function(num, decimalPlaces) {
            return decimalAdjust('trunc', num, decimalPlaces);
        },
        // Format using fixed-point notation
        toFixed: function(num, decimalPlaces) {
            return decimalAdjust('round', num, decimalPlaces).toFixed(decimalPlaces);
        }
    };
})();

// test rounding of half
console.log(DecimalPrecision2.round(0.5));  // 1
console.log(DecimalPrecision2.round(-0.5)); // -1

// testing very small numbers
console.log(DecimalPrecision2.ceil(1e-8, 2) === 0.01);
console.log(DecimalPrecision2.floor(1e-8, 2) === 0);

// testing simple cases
console.log(DecimalPrecision2.round(5.12, 1) === 5.1);
console.log(DecimalPrecision2.round(-5.12, 1) === -5.1);
console.log(DecimalPrecision2.ceil(5.12, 1) === 5.2);
console.log(DecimalPrecision2.ceil(-5.12, 1) === -5.1);
console.log(DecimalPrecision2.floor(5.12, 1) === 5.1);
console.log(DecimalPrecision2.floor(-5.12, 1) === -5.2);
console.log(DecimalPrecision2.trunc(5.12, 1) === 5.1);
console.log(DecimalPrecision2.trunc(-5.12, 1) === -5.1);

// testing edge cases for round
console.log(DecimalPrecision2.round(1.005, 2) === 1.01);
console.log(DecimalPrecision2.round(39.425, 2) === 39.43);
console.log(DecimalPrecision2.round(-1.005, 2) === -1.01);
console.log(DecimalPrecision2.round(-39.425, 2) === -39.43);

// testing edge cases for ceil
console.log(DecimalPrecision2.ceil(9.13, 2) === 9.13);
console.log(DecimalPrecision2.ceil(65.18, 2) === 65.18);
console.log(DecimalPrecision2.ceil(-2.26, 2) === -2.26);
console.log(DecimalPrecision2.ceil(-18.15, 2) === -18.15);

// testing edge cases for floor
console.log(DecimalPrecision2.floor(2.26, 2) === 2.26);
console.log(DecimalPrecision2.floor(18.15, 2) === 18.15);
console.log(DecimalPrecision2.floor(-9.13, 2) === -9.13);
console.log(DecimalPrecision2.floor(-65.18, 2) === -65.18);

// testing edge cases for trunc
console.log(DecimalPrecision2.trunc(2.26, 2) === 2.26);
console.log(DecimalPrecision2.trunc(18.15, 2) === 18.15);
console.log(DecimalPrecision2.trunc(-2.26, 2) === -2.26);
console.log(DecimalPrecision2.trunc(-18.15, 2) === -18.15);

// testing round to tens and hundreds
console.log(DecimalPrecision2.round(1262.48, -1) === 1260);
console.log(DecimalPrecision2.round(1262.48, -2) === 1300);

// testing toFixed()
console.log(DecimalPrecision2.toFixed(1.005, 2) === "1.01");

해결책 3: 더블 라운딩

이 솔루션에서는 toPrecision() 메서드를 사용하여 부동 소수점 반올림 오류를 제거합니다.

// Solution 3
var DecimalPrecision3 = (function() {
    if (Math.trunc === undefined) {
        Math.trunc = function(v) {
            return v < 0 ? Math.ceil(v) : Math.floor(v);
        };
    }
    var powers = [
        1e0,  1e1,  1e2,  1e3,  1e4,  1e5,  1e6,  1e7,
        1e8,  1e9,  1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
        1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22
    ];
    var intpow10 = function(power) {
        if (power < 0 || power > 22) {
            return Math.pow(10, power);
        }
        return powers[power];
    };
    // Eliminate binary floating-point inaccuracies.
    var stripError = function(num) {
        if (Number.isInteger(num))
            return num;
        return parseFloat(num.toPrecision(15));
    };
    var decimalAdjust = function myself(type, num, decimalPlaces) {
        if (type === 'round' && num < 0)
            return -myself(type, -num, decimalPlaces);
        var p = intpow10(decimalPlaces || 0);
        var n = stripError(num * p);
        return Math[type](n) / p;
    };
    return {
        // Decimal round (half away from zero)
        round: function(num, decimalPlaces) {
            return decimalAdjust('round', num, decimalPlaces);
        },
        // Decimal ceil
        ceil: function(num, decimalPlaces) {
            return decimalAdjust('ceil', num, decimalPlaces);
        },
        // Decimal floor
        floor: function(num, decimalPlaces) {
            return decimalAdjust('floor', num, decimalPlaces);
        },
        // Decimal trunc
        trunc: function(num, decimalPlaces) {
            return decimalAdjust('trunc', num, decimalPlaces);
        },
        // Format using fixed-point notation
        toFixed: function(num, decimalPlaces) {
            return decimalAdjust('round', num, decimalPlaces).toFixed(decimalPlaces);
        }
    };
})();

// test rounding of half
console.log(DecimalPrecision3.round(0.5));  // 1
console.log(DecimalPrecision3.round(-0.5)); // -1

// testing very small numbers
console.log(DecimalPrecision3.ceil(1e-8, 2) === 0.01);
console.log(DecimalPrecision3.floor(1e-8, 2) === 0);

// testing simple cases
console.log(DecimalPrecision3.round(5.12, 1) === 5.1);
console.log(DecimalPrecision3.round(-5.12, 1) === -5.1);
console.log(DecimalPrecision3.ceil(5.12, 1) === 5.2);
console.log(DecimalPrecision3.ceil(-5.12, 1) === -5.1);
console.log(DecimalPrecision3.floor(5.12, 1) === 5.1);
console.log(DecimalPrecision3.floor(-5.12, 1) === -5.2);
console.log(DecimalPrecision3.trunc(5.12, 1) === 5.1);
console.log(DecimalPrecision3.trunc(-5.12, 1) === -5.1);

// testing edge cases for round
console.log(DecimalPrecision3.round(1.005, 2) === 1.01);
console.log(DecimalPrecision3.round(39.425, 2) === 39.43);
console.log(DecimalPrecision3.round(-1.005, 2) === -1.01);
console.log(DecimalPrecision3.round(-39.425, 2) === -39.43);

// testing edge cases for ceil
console.log(DecimalPrecision3.ceil(9.13, 2) === 9.13);
console.log(DecimalPrecision3.ceil(65.18, 2) === 65.18);
console.log(DecimalPrecision3.ceil(-2.26, 2) === -2.26);
console.log(DecimalPrecision3.ceil(-18.15, 2) === -18.15);

// testing edge cases for floor
console.log(DecimalPrecision3.floor(2.26, 2) === 2.26);
console.log(DecimalPrecision3.floor(18.15, 2) === 18.15);
console.log(DecimalPrecision3.floor(-9.13, 2) === -9.13);
console.log(DecimalPrecision3.floor(-65.18, 2) === -65.18);

// testing edge cases for trunc
console.log(DecimalPrecision3.trunc(2.26, 2) === 2.26);
console.log(DecimalPrecision3.trunc(18.15, 2) === 18.15);
console.log(DecimalPrecision3.trunc(-2.26, 2) === -2.26);
console.log(DecimalPrecision3.trunc(-18.15, 2) === -18.15);

// testing round to tens and hundreds
console.log(DecimalPrecision3.round(1262.48, -1) === 1260);
console.log(DecimalPrecision3.round(1262.48, -2) === 1300);

// testing toFixed()
console.log(DecimalPrecision3.toFixed(1.005, 2) === "1.01");

솔루션 4: 더블 라운딩 v2

3을 합니다.toPrecision()★★★★★★ 。

// Solution 4
var DecimalPrecision4 = (function() {
    if (Math.trunc === undefined) {
        Math.trunc = function(v) {
            return v < 0 ? Math.ceil(v) : Math.floor(v);
        };
    }
    var powers = [
        1e0,  1e1,  1e2,  1e3,  1e4,  1e5,  1e6,  1e7,
        1e8,  1e9,  1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
        1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22
    ];
    var intpow10 = function(power) {
        if (power < 0 || power > 22) {
            return Math.pow(10, power);
        }
        return powers[power];
    };
    var toPrecision = function(num, significantDigits) {
        // Return early for ±0, NaN and Infinity.
        if (!num || !Number.isFinite(num))
            return num;
        // Compute shift of the decimal point (sf - leftSidedDigits).
        var shift = significantDigits - 1 - Math.floor(Math.log10(Math.abs(num)));
        // Return if rounding to the same or higher precision.
        var decimalPlaces = 0;
        for (var p = 1; num != Math.round(num * p) / p; p *= 10) decimalPlaces++;
        if (shift >= decimalPlaces)
            return num;
        // Round to "shift" fractional digits
        var scale = intpow10(Math.abs(shift));
        return shift > 0 ?
            Math.round(num * scale) / scale :
            Math.round(num / scale) * scale;
    };
    // Eliminate binary floating-point inaccuracies.
    var stripError = function(num) {
        if (Number.isInteger(num))
            return num;
        return toPrecision(num, 15);
    };
    var decimalAdjust = function myself(type, num, decimalPlaces) {
        if (type === 'round' && num < 0)
            return -myself(type, -num, decimalPlaces);
        var p = intpow10(decimalPlaces || 0);
        var n = stripError(num * p);
        return Math[type](n) / p;
    };
    return {
        // Decimal round (half away from zero)
        round: function(num, decimalPlaces) {
            return decimalAdjust('round', num, decimalPlaces);
        },
        // Decimal ceil
        ceil: function(num, decimalPlaces) {
            return decimalAdjust('ceil', num, decimalPlaces);
        },
        // Decimal floor
        floor: function(num, decimalPlaces) {
            return decimalAdjust('floor', num, decimalPlaces);
        },
        // Decimal trunc
        trunc: function(num, decimalPlaces) {
            return decimalAdjust('trunc', num, decimalPlaces);
        },
        // Format using fixed-point notation
        toFixed: function(num, decimalPlaces) {
            return decimalAdjust('round', num, decimalPlaces).toFixed(decimalPlaces);
        }
    };
})();

// test rounding of half
console.log(DecimalPrecision4.round(0.5));  // 1
console.log(DecimalPrecision4.round(-0.5)); // -1

// testing very small numbers
console.log(DecimalPrecision4.ceil(1e-8, 2) === 0.01);
console.log(DecimalPrecision4.floor(1e-8, 2) === 0);

// testing simple cases
console.log(DecimalPrecision4.round(5.12, 1) === 5.1);
console.log(DecimalPrecision4.round(-5.12, 1) === -5.1);
console.log(DecimalPrecision4.ceil(5.12, 1) === 5.2);
console.log(DecimalPrecision4.ceil(-5.12, 1) === -5.1);
console.log(DecimalPrecision4.floor(5.12, 1) === 5.1);
console.log(DecimalPrecision4.floor(-5.12, 1) === -5.2);
console.log(DecimalPrecision4.trunc(5.12, 1) === 5.1);
console.log(DecimalPrecision4.trunc(-5.12, 1) === -5.1);

// testing edge cases for round
console.log(DecimalPrecision4.round(1.005, 2) === 1.01);
console.log(DecimalPrecision4.round(39.425, 2) === 39.43);
console.log(DecimalPrecision4.round(-1.005, 2) === -1.01);
console.log(DecimalPrecision4.round(-39.425, 2) === -39.43);

// testing edge cases for ceil
console.log(DecimalPrecision4.ceil(9.13, 2) === 9.13);
console.log(DecimalPrecision4.ceil(65.18, 2) === 65.18);
console.log(DecimalPrecision4.ceil(-2.26, 2) === -2.26);
console.log(DecimalPrecision4.ceil(-18.15, 2) === -18.15);

// testing edge cases for floor
console.log(DecimalPrecision4.floor(2.26, 2) === 2.26);
console.log(DecimalPrecision4.floor(18.15, 2) === 18.15);
console.log(DecimalPrecision4.floor(-9.13, 2) === -9.13);
console.log(DecimalPrecision4.floor(-65.18, 2) === -65.18);

// testing edge cases for trunc
console.log(DecimalPrecision4.trunc(2.26, 2) === 2.26);
console.log(DecimalPrecision4.trunc(18.15, 2) === 18.15);
console.log(DecimalPrecision4.trunc(-2.26, 2) === -2.26);
console.log(DecimalPrecision4.trunc(-18.15, 2) === -18.15);

// testing round to tens and hundreds
console.log(DecimalPrecision4.round(1262.48, -1) === 1260);
console.log(DecimalPrecision4.round(1262.48, -2) === 1300);

// testing toFixed()
console.log(DecimalPrecision4.toFixed(1.005, 2) === "1.01");

벤치마크

http://jsbench.github.io/ #31ec3a8b3d22bd840f8e6822e681a3ac

다음은 Chrome 85.0.4183.83 위의 솔루션에서 초당 작업 수를 비교한 벤치마크입니다.브라우저마다 확실히 다르기 때문에 마일리지가 다를 수 있습니다.

벤치마크 비교 (주의: 많을수록 좋습니다)

벤치마크 스크린샷을 추가해 주셔서 @Mike님 감사합니다.

이 질문은 복잡하다.

를 들어, ' 가정해봅시다.roundTo2DP(num)float를 인수로 하여 소수점 2자리 반올림된 값을 반환합니다.이러한 표현은 각각 무엇을 평가해야 합니까?

  • roundTo2DP(0.014999999999999999)
  • roundTo2DP(0.0150000000000000001)
  • roundTo2DP(0.015)

첫 번째 예제는 0.01로 반올림해야 합니다(0.02보다 0.01에 가깝기 때문에). 나머지 두 예제는 0.02로 반올림해야 합니다(0.0150000000000000001은 0.01보다 0.02에 가깝고 0.015는 두 예제의 중간이며 이러한 숫자를 반올림하는 수학적 규칙이 있기 때문에).

수단점은, 그것은 바로 '비슷하다'는 입니다.roundTo2DP 개의 번호가 모두 같은 번호이기 때문에, 그러한 명확한 답을 주는 것은 불가능하다고 생각됩니다.IEEE 754 바이너리 부동소수점 번호(JavaScript에서 사용되는 종류)는 대부분의 정수 이외의 숫자를 정확하게 나타낼 수 없기 때문에 위의 세 가지 숫자 모두 가까운 유효한 부동소수점 번호로 반올림됩니다.이 숫자는 공교롭게도 정확히

0.01499999999999999944488848768742172978818416595458984375

0.02보다 0.01에 가깝습니다.

브라우저 콘솔, 노드셸 또는 기타 JavaScript 인터프리터에서 3개의 번호가 모두 동일한 것을 확인할 수 있습니다.비교만 하면 됩니다.

> 0.014999999999999999 === 0.0150000000000000001
true

이렇게 쓰면m = 0.0150000000000000001 정확한 은 에 가깝습니다.0.010.02m★★★★★★★★★★★…

> var m = 0.0150000000000000001;
> console.log(String(m));
0.015
> var m = 0.014999999999999999;
> console.log(String(m));
0.015

...0.015를 얻으면 0.02로 반올림합니다.이 숫자는 앞서 말한 56자리 소수점 이하 숫자와는 다릅니다.그럼 이게 무슨 어둠의 마법이죠?

정답은 ECMAScript 사양 섹션 7.1.12.1: ToString이 번호 유형에 적용됨에서 확인할 수 있습니다.여기에서는 일부 숫자 m을 문자열로 변환하는 규칙을 설명합니다.키 부분은 포인트5 입니다.여기서 m의 String 표현에 사용되는 자리수의 정수 s가 생성됩니다.

n, k s는 k 1 1, 10k-1 s s < 10k, s × 10의n-k 숫자 값은 m, k는 가능한 한 작은 정수이다.k는 s의 10진수 표현 자리수이며, s는 10으로 나누어지지 않으며, s의 최하위 자리수는 이러한 기준에 의해 반드시 일의로 결정되는 것은 아닙니다.

여기서 중요한 것은 "k는 가능한 한 작다"는 요건입니다.그 요건이 의미하는 것은 번호가 주어졌을 때m의 값, " " "String(m)가능한 한 최소 자리수를 가지면서도 다음과 같은 요건을 충족해야 합니다.Number(String(m)) === m가 있기 0.015 === 0.0150000000000000001그 이유가 String(0.0150000000000000001) === '0.015'사실이어야 합니다.

이 중 어떤 .roundTo2DP(m) 돌아와야 합니다.한다면m의 정확한 값은 0.014999999999999999448848768742172978818818416595458984375이지만 문자열 표현은 0.015입니다. 그렇다면 소수점 두 자리로 반올림했을 때 정답은 무엇입니까?

이것에 대한 정답은 단 한 개도 없다.사용 사례에 따라 다릅니다.다음과 같은 경우 String 표현을 존중하고 위로 반올림하는 것이 좋습니다.

  • 표현되는 가치는 본질적으로 별개의 것으로, 예를 들어 디나르와 같은 3자리 소수점 통화의 통화량이다.이 경우 0.015와 같은 숫자의 참값은 0.015이고 0.0149999999...2진수 부동소수점에서의 표현은 반올림 오류입니다.(물론 많은 사람들은 이러한 값을 처리하기 위해 10진수 라이브러리를 사용해야 하며 처음부터 2진수 부동소수점 숫자로 표현해서는 안 된다고 주장합니다.)
  • 사용자가 값을 입력했습니다.이 경우에도 입력된 정확한 10진수는 가장 가까운 이진 부동소수점 표현보다 '참'입니다.

한편, 바이너리 부동소수점 값을 존중하고 값이 본질적으로 연속적인 척도(예를 들어 센서에서 읽은 값)인 경우 아래쪽으로 반올림하는 것이 좋습니다.

이 두 가지 접근 방식에는 다른 코드가 필요합니다.숫자의 문자열 표현을 존중하기 위해 학교에서 숫자를 반올림하는 방법을 배웠을 때와 같은 알고리즘을 사용하여 숫자별로 문자열 표현에 직접 작용하는 자체 반올림을 구현할 수 있습니다.다음 예시는 소수점 뒤의 끝자리 제로를 제거하여 소수점 2자리까지 숫자를 나타내는 OP의 요건을 고려한 것입니다.물론 필요에 따라 숫자를 조정해야 할 수도 있습니다.

/**
 * Converts num to a decimal string (if it isn't one already) and then rounds it
 * to at most dp decimal places.
 *
 * For explanation of why you'd want to perform rounding operations on a String
 * rather than a Number, see http://stackoverflow.com/a/38676273/1709587
 *
 * @param {(number|string)} num
 * @param {number} dp
 * @return {string}
 */
function roundStringNumberWithoutTrailingZeroes (num, dp) {
    if (arguments.length != 2) throw new Error("2 arguments required");

    num = String(num);
    if (num.indexOf('e+') != -1) {
        // Can't round numbers this large because their string representation
        // contains an exponent, like 9.99e+37
        throw new Error("num too large");
    }
    if (num.indexOf('.') == -1) {
        // Nothing to do
        return num;
    }

    var parts = num.split('.'),
        beforePoint = parts[0],
        afterPoint = parts[1],
        shouldRoundUp = afterPoint[dp] >= 5,
        finalNumber;

    afterPoint = afterPoint.slice(0, dp);
    if (!shouldRoundUp) {
        finalNumber = beforePoint + '.' + afterPoint;
    } else if (/^9+$/.test(afterPoint)) {
        // If we need to round up a number like 1.9999, increment the integer
        // before the decimal point and discard the fractional part.
        finalNumber = Number(beforePoint)+1;
    } else {
        // Starting from the last digit, increment digits until we find one
        // that is not 9, then stop
        var i = dp-1;
        while (true) {
            if (afterPoint[i] == '9') {
                afterPoint = afterPoint.substr(0, i) +
                             '0' +
                             afterPoint.substr(i+1);
                i--;
            } else {
                afterPoint = afterPoint.substr(0, i) +
                             (Number(afterPoint[i]) + 1) +
                             afterPoint.substr(i+1);
                break;
            }
        }

        finalNumber = beforePoint + '.' + afterPoint;
    }

    // Remove trailing zeroes from fractional part before returning
    return finalNumber.replace(/0+$/, '')
}

사용 예:

> roundStringNumberWithoutTrailingZeroes(1.6, 2)
'1.6'
> roundStringNumberWithoutTrailingZeroes(10000, 2)
'10000'
> roundStringNumberWithoutTrailingZeroes(0.015, 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes('0.015000', 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes(1, 1)
'1'
> roundStringNumberWithoutTrailingZeroes('0.015', 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes(0.01499999999999999944488848768742172978818416595458984375, 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes('0.01499999999999999944488848768742172978818416595458984375', 2)
'0.01'

위의 함수는 사용자가 잘못 입력한 숫자가 반올림되는 것을 방지하기 위해 사용하는 함수입니다.

(대안으로서 round 10 라이브러리를 시험해 볼 수도 있습니다).이 라이브러리는 전혀 다른 실장에서의 동작과 같은 기능을 제공합니다).

하지만 두 번째 종류의 숫자 - 소수 자릿수가 적은 대략적인 소수 표현이 더 많은 소수 자릿수보다 더 정확하다고 생각할 이유가 없는 연속적인 척도에서 얻은 값인 숫자를 가지고 있다면 어떨까요? 경우 String 표현은 (스펙에서 설명한 바와 같이) 이미 반올림되어 있기 때문에 존중하고 싶지 않습니다.또, 「0.01499999...」라고 하는 실수를 하고 싶지 않습니다.375는 0.015로 반올림하고 0.02로 반올림하니 0.01499999...375는 0.02인치로 반올림.

여기서는 빌트인 방식을 간단하게 사용할 수 있습니다.전화에 의해 주의해 주세요.Number()"String"에 의해 반환된 toFixedString 표현에 제로가 없는 번호가 표시됩니다(JavaScript가 앞부분에서 설명한 숫자의 String 표현을 계산하는 방법).

/**
 * Takes a float and rounds it to at most dp decimal places. For example
 *
 *     roundFloatNumberWithoutTrailingZeroes(1.2345, 3)
 *
 * returns 1.234
 *
 * Note that since this treats the value passed to it as a floating point
 * number, it will have counterintuitive results in some cases. For instance,
 * 
 *     roundFloatNumberWithoutTrailingZeroes(0.015, 2)
 *
 * gives 0.01 where 0.02 might be expected. For an explanation of why, see
 * http://stackoverflow.com/a/38676273/1709587. You may want to consider using the
 * roundStringNumberWithoutTrailingZeroes function there instead.
 *
 * @param {number} num
 * @param {number} dp
 * @return {number}
 */
function roundFloatNumberWithoutTrailingZeroes (num, dp) {
    var numToFixedDp = Number(num).toFixed(dp);
    return Number(numToFixedDp);
}

.toFixed() ★★★★★★★★★★★★★★★★★」.toPrecision():

http://www.javascriptkit.com/javatutors/formatnumber.shtml

.toFixed(NumberOfDecimalPlaces).

var str = 10.234.toFixed(2); // => '10.23'
var number = Number(str); // => 10.23

여기서 찾은 정답은 하나도 틀리지 않았어요. 악취나는 치즈맨모이라고 했는데, 모두 숫자를 반올림했군요.

반올림하려면 다음을 사용합니다.

Math.ceil(num * 100)/100;

간단한 방법은 다음과 같습니다.

Math.round(value * 100) / 100

다른 기능을 만들어 사용할 수도 있습니다.

function roundToTwo(value) {
    return(Math.round(value * 100) / 100);
}

그러면 당신은 단순히 그 가치를 전달할 것입니다.

두 번째 파라미터를 추가하여 임의의 소수점 수로 반올림할 수 있습니다.

function myRound(value, places) {
    var multiplier = Math.pow(10, places);

    return (Math.round(value * multiplier) / multiplier);
}

정밀한 반올림법.출처 : Mozilla

(function(){

    /**
     * Decimal adjustment of a number.
     *
     * @param   {String}    type    The type of adjustment.
     * @param   {Number}    value   The number.
     * @param   {Integer}   exp     The exponent (the 10 logarithm of the adjustment base).
     * @returns {Number}            The adjusted value.
     */
    function decimalAdjust(type, value, exp) {
        // If the exp is undefined or zero...
        if (typeof exp === 'undefined' || +exp === 0) {
            return Math[type](value);
        }
        value = +value;
        exp = +exp;
        // If the value is not a number or the exp is not an integer...
        if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {
            return NaN;
        }
        // Shift
        value = value.toString().split('e');
        value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp)));
        // Shift back
        value = value.toString().split('e');
        return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp));
    }

    // Decimal round
    if (!Math.round10) {
        Math.round10 = function(value, exp) {
            return decimalAdjust('round', value, exp);
        };
    }
    // Decimal floor
    if (!Math.floor10) {
        Math.floor10 = function(value, exp) {
            return decimalAdjust('floor', value, exp);
        };
    }
    // Decimal ceil
    if (!Math.ceil10) {
        Math.ceil10 = function(value, exp) {
            return decimalAdjust('ceil', value, exp);
        };
    }
})();

예:

// Round
Math.round10(55.55, -1); // 55.6
Math.round10(55.549, -1); // 55.5
Math.round10(55, 1); // 60
Math.round10(54.9, 1); // 50
Math.round10(-55.55, -1); // -55.5
Math.round10(-55.551, -1); // -55.6
Math.round10(-55, 1); // -50
Math.round10(-55.1, 1); // -60
Math.round10(1.005, -2); // 1.01 -- compare this with Math.round(1.005*100)/100 above
// Floor
Math.floor10(55.59, -1); // 55.5
Math.floor10(59, 1); // 50
Math.floor10(-55.51, -1); // -55.6
Math.floor10(-51, 1); // -60
// Ceil
Math.ceil10(55.51, -1); // 55.6
Math.ceil10(51, 1); // 60
Math.ceil10(-55.59, -1); // -55.5
Math.ceil10(-59, 1); // -50

다음과 같은 이점이 있습니다.

var result = Math.round(input*100)/100;

자세한 내용은 Math.round(num) vs num.toFixed(0) 및 브라우저의 불일치를 참조하십시오.

는 Math.round()가 정답을 제시하지 않았습니다.ToFixed(2)가 더 잘 작동한다는 것을 알게 되었습니다.다음으로 두 가지 예를 제시하겠습니다.

console.log(Math.round(43000 / 80000) * 100); // wrong answer

console.log(((43000 / 80000) * 100).toFixed(2)); // correct answer

합니다.Number(x).toFixed(2);

+(10).toFixed(2); // = 10
+(10.12345).toFixed(2); // = 10.12

(10).toFixed(2); // = 10.00
(10.12345).toFixed(2); // = 10.12

Lodash 라이브러리를 사용하는 경우 다음과 같이 Lodash의 라운드 방식을 사용할 수 있습니다.

_.round(number, precision)

예를 들어 다음과 같습니다.

_.round(1.7777777, 2) = 1.78

다음과 같은 경량 솔루션을 사용해 보십시오.

function round(x, digits){
  return parseFloat(x.toFixed(digits))
}

 round(1.222,  2);
 // 1.22
 round(1.222, 10);
 // 1.222

그것을 하는 데는 몇 가지 방법이 있다.나 같은 사람에게는 로다쉬의 변종이

function round(number, precision) {
    var pair = (number + 'e').split('e')
    var value = Math.round(pair[0] + 'e' + (+pair[1] + precision))
    pair = (value + 'e').split('e')
    return +(pair[0] + 'e' + (+pair[1] - precision))
}

사용방법:

round(0.015, 2) // 0.02
round(1.005, 2) // 1.01

Lodash를 사용하는 jQuery를 .round메서드를 지정합니다.

2017
코드만 하세요..toFixed()

number = 1.2345;
number.toFixed(2) // "1.23"

엄밀하게 가 있는 는, 「」를 사용할 수 .replace

number = 1; // "1"
number.toFixed(5).replace(/\.?0*$/g,'');

ES6에서는 toPrecision을 사용하여 (통계정보를 덮어쓰거나 회피책을 작성하지 않고) '적절한' 방법이 있습니다.

var x = 1.49999999999;
console.log(x.toPrecision(4));
console.log(x.toPrecision(3));
console.log(x.toPrecision(2));

var y = Math.PI;
console.log(y.toPrecision(6));
console.log(y.toPrecision(5));
console.log(y.toPrecision(4));

var z = 222.987654
console.log(z.toPrecision(6));
console.log(z.toPrecision(5));
console.log(z.toPrecision(4));

그냥 '그냥' 하면 요.parseFloat0'은 '0'입니다.

console.log(parseFloat((1.4999).toPrecision(3)));
console.log(parseFloat((1.005).toPrecision(3)));
console.log(parseFloat((1.0051).toPrecision(3)));

그러나 플로트 분율이 처리되는 방식에 따라 달라지기 때문에 '1.005 반올림 문제'는 해결되지 않습니다.

console.log(1.005 - 0.005);

라이브러리를 열고 있는 경우 bignumber.js를 사용할 수 있습니다.

console.log(1.005 - 0.005);
console.log(new BigNumber(1.005).minus(0.005));

console.log(new BigNumber(1.005).round(4));
console.log(new BigNumber(1.005).round(3));
console.log(new BigNumber(1.005).round(2));
console.log(new BigNumber(1.005).round(1));
<script src="https://cdnjs.cloudflare.com/ajax/libs/bignumber.js/2.3.0/bignumber.min.js"></script>

가장 쉬운 방법은 toFixed를 사용한 다음 Number 함수를 사용하여 후행 0을 제거하는 것입니다.

const number = 15.5;
Number(number.toFixed(2)); // 15.5
const number = 1.7777777;
Number(number.toFixed(2)); // 1.78

MarkGLavamantis는 받아들여진 솔루션보다 훨씬 더 나은 솔루션을 제공했습니다.그들이 더 많은 표를 얻지 못하는 것은 유감이다!

MDN을 기반으로 부동소수점 소수점 문제를 해결하기 위해 사용하는 함수는 다음과 같습니다. Lavamantis의 솔루션보다 더 일반적이지만 간결하지는 않습니다.

function round(value, exp) {
  if (typeof exp === 'undefined' || +exp === 0)
    return Math.round(value);

  value = +value;
  exp  = +exp;

  if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0))
    return NaN;

  // Shift
  value = value.toString().split('e');
  value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)));

  // Shift back
  value = value.toString().split('e');
  return +(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp));
}

사용처:

round(10.8034, 2);      // Returns 10.8
round(1.275, 2);        // Returns 1.28
round(1.27499, 2);      // Returns 1.27
round(1.2345678e+2, 2); // Returns 123.46

라바만티스의 해결책과 비교하면...

round(1234.5678, -2); // Returns 1200
round("123.45");      // Returns 123

이러한 반올림을 실현하는 한 가지 방법은 Number.protype.toLocaleString()사용하는 것입니다.

myNumber.toLocaleString('en', {maximumFractionDigits:2, useGrouping:false})

이렇게 하면 원하는 출력이 그대로 제공되지만 문자열로 제공됩니다.원하는 데이터 유형이 아닌 경우에도 숫자로 변환할 수 있습니다.

당신에게 도움이 될 수도 있지만

Math.round(num * 100)/100;

toFixed와 round의 차이를 알 수 있습니다.Math.round(num) vs num.toFixed(0) 브라우저의 불일치를 확인할 수 있습니다.

(함수를 쓰지 않고) 다른 간단한 솔루션에서는 fixed()를 사용하여 다시 float로 변환할 수 있습니다.

예를 들어 다음과 같습니다.

var objNumber = 1201203.1256546456;
objNumber = parseFloat(objNumber.toFixed(2))

이것은 가장 심플하고 우아한 솔루션입니다(그리고 저는 세계 최고입니다).

function roundToX(num, X) {    
    return +(Math.round(num + "e+"+X)  + "e-"+X);
}
//roundToX(66.66666666,2) => 66.67
//roundToX(10,2) => 10
//roundToX(10.904,2) => 10.9

폴백 값을 사용한 최신 구문 대체

const roundToX = (num = 0, X = 20) => +(Math.round(num + `e${X}`)  + `e-${X}`)
var roundUpto = function(number, upto){
    return Number(number.toFixed(upto));
}
roundUpto(0.1464676, 2);

toFixed(2): 여기 2는 이 숫자를 반올림하는 자리수입니다.

이 솔루션의 다양한 어댑테이션에 대한 자세한 내용과 성능 내역은 @AmrAli의 답변을 참조하십시오.

var DecimalPrecision = (function(){
        if (Number.EPSILON === undefined) {
            Number.EPSILON = Math.pow(2, -52);
        }
        if(Number.isInteger === undefined){
            Number.isInteger = function(value) {
                return typeof value === 'number' && 
                isFinite(value) && 
                Math.floor(value) === value;
            };
        }
        this.isRound = function(n,p){
            let l = n.toString().split('.')[1].length;
            return (p >= l);
        }
        this.round = function(n, p=2){
            if(Number.isInteger(n) || this.isRound(n,p))
                return n;
            let r = 0.5 * Number.EPSILON * n;
            let o = 1; while(p-- > 0) o *= 10;
            if(n<0)
                o *= -1;
            return Math.round((n + r) * o) / o;
        }
        this.ceil = function(n, p=2){
            if(Number.isInteger(n) || this.isRound(n,p))
                return n;
            let r = 0.5 * Number.EPSILON * n;
            let o = 1; while(p-- > 0) o *= 10;
            
            return Math.ceil((n + r) * o) / o;
        }
        this.floor = function(n, p=2){
            if(Number.isInteger(n) || this.isRound(n,p))
                return n;
            let r = 0.5 * Number.EPSILON * n;
            let o = 1; while(p-- > 0) o *= 10;
            
            return Math.floor((n + r) * o) / o;
        }
        return this;
    })();
    console.log(DecimalPrecision.round(1.005));
    console.log(DecimalPrecision.ceil(1.005));
    console.log(DecimalPrecision.floor(1.005));
    console.log(DecimalPrecision.round(1.0049999));
    console.log(DecimalPrecision.ceil(1.0049999));
    console.log(DecimalPrecision.floor(1.0049999));
    console.log(DecimalPrecision.round(2.175495134384,7));
    console.log(DecimalPrecision.round(2.1753543549,8));
    console.log(DecimalPrecision.round(2.1755465135353,4));
    console.log(DecimalPrecision.ceil(17,4));
    console.log(DecimalPrecision.ceil(17.1,4));
    console.log(DecimalPrecision.ceil(17.1,15));

가장 쉬운 방법:

+num.toFixed(2)

문자열로 변환한 다음 정수/플로트로 다시 변환합니다.

언급URL : https://stackoverflow.com/questions/11832914/how-to-round-to-at-most-2-decimal-places-if-necessary

반응형