> 웹 프론트엔드 > JS 튜토리얼 > 숫자 (). tofixed () 반올림 오류 : 깨지지 만 수정 가능

숫자 (). tofixed () 반올림 오류 : 깨지지 만 수정 가능

Jennifer Aniston
풀어 주다: 2025-02-15 10:02:12
원래의
188명이 탐색했습니다.

Number().toFixed() Rounding Errors: Broken But Fixable 이 기사는 원래 David Kaye의 블로그

에 출판되었습니다 나는 시도한 모든 JavaScript 환경 (Chrome, Firefox, Internet Explorer, Brave 및 Node.js)에서 숫자 (). tofixed ()에서 반올림 오류를 발견했습니다. 놀랍게도, 수정은 매우 간단합니다. 계속 읽으십시오 ... 키 포인트

javaScript의 숫자 (). tofixed () 함수는 여러 환경 (Chrome, Firefox, Internet Explorer, Brave 및 Node.js)에서 반올림 오류가 있습니다. 이 오차는 일관되지 않으며, 10 진수 부품의 마지막 상당수 수가 5 일 때 발생하며, 트림 길이는 10 진 부분에서 하나만 감소시키고 다른 정수 값이 적용됩니다.

값에 소수점이 포함 된 경우 수정할 값의 문자열 버전의 끝에 "1"을 추가 하여이 오류를 수정할 수 있습니다. 이 솔루션은 하위 수준의 이진 또는 부동 소수점 작업의 재검토가 필요하지 않습니다.

모든 구현이 수정 될 때까지 polyfill을 사용하여 tofixed () 함수를 재정의 할 수 있습니다. 그러나 모든 사람 이이 접근법에 만족하는 것은 아닙니다. Polyfill에는 프로토 타입이 포함되며 Tofixed Function과 결과 길이가 0인지 확인합니다. 워밍업

intl.numberformat#format ()과 동일한 함수를 수행하는 디지털 형식 형식 기능을 수정할 때이 버전에서 tofixed ()에서 반올림 오류를 발견했습니다.
  • 실패한 테스트는 여기서 42 행에 있습니다. 2017 년 12 월까지 찾지 못해서 다른 문제를 확인하게되었습니다.
  • 이 질문에 대한 내 트윗을 참조하십시오
  • 오류 경보 intl.numberformat 와 비교하십시오
  • 요약 polyfill
오류 보고서

tofixed ()를 사용할 때 오류보고의 오랜 기록이 있습니다.

크롬 Firefox Firefox, 도 참조하십시오 인터넷 익스플로러

이 문제에 대한 StackoverFlow 문제의 짧은 예는 다음과 같습니다.

예 1
(1.015).toFixed(2) // 返回 "1.01" 而不是 "1.02"
로그인 후 복사
로그인 후 복사
<🎜 🎜> 예제 2 <🎜 🎜>

일반적으로, 이들은 <🎜 a <🎜 a <🎜 a

value의 오류가 있지만, 오류 결과를 반환하는 값의 범위 나 패턴은 없습니다 (적어도 나는 그것을 찾지 못했습니다. , 나는 무언가를 놓쳤을 수도 있습니다). 이를 통해 프로그래머는 작은 문제에 집중하고 더 큰 패턴을 볼 수 없습니다. 나는 이것에 대해 그들을 비난하지 않습니다.

<<> 패턴을 찾으십시오
  • 입력에 기반한 예상치 못한 결과는 입력의 공유 모드에서 시작해야합니다. 따라서 숫자 (). tofixed ()의 사양을 검토하는 대신 각 시리즈에 오류가 나타나는 위치를 결정하기 위해 일련의 값으로 테스트하는 데 중점을 두었습니다.
  • 테스트 기능 <🎜 🎜> i 나는 다음 테스트 함수를 만들어 1에서 maxValue 일련의 정수에서 tofixed () 작업을 수행하여 각 정수에 .005와 같은 10 진수를 추가했습니다. tofixed ()의 고정 된 (숫자 숫자) 매개 변수는 십진 값의 길이에 따라 계산됩니다.
  • (1.015).toFixed(2) // 返回 "1.01" 而不是 "1.02"
    로그인 후 복사
    로그인 후 복사

    사용량 <🎜 🎜> 다음 예제는 정수 1에서 128에서 작업을 수행하고 각 정수에 대해 10 진수 .015를 추가하고 "예기치 않은"결과를 반환합니다. 각 결과에는 주어진, 예상 및 실제 필드가 포함됩니다. 여기서 우리는 해당 배열을 사용하고 각 항목을 인쇄합니다.

    출력 <🎜 🎜> 이 상황의 경우 예상치 못한 결과가 6 개 있습니다.
    function test({fraction, maxValue}) {
      fraction = fraction.toString()
      var fixLength = fraction.split('.')[1].length - 1
    
      var last = Number(fraction.charAt(fraction.length - 1))
      var fixDigit = Number(fraction.charAt(fraction.length - 2))
    
      last >= 5 && (fixDigit = fixDigit + 1)
    
      var expectedFraction = fraction.replace(/[\d]{2,2}$/, fixDigit)
    
      return Array(maxValue).fill(0)
        .map(function(ignoreValue, index) {
          return index + 1
        })
        .filter(function(integer) {
          var number = integer + Number(fraction)
          var actual = number.toFixed(fixLength)
          var expected = Number(number + '1').toFixed(fixLength)
    
          return expected != actual
        })
        .map(function(integer) {
          var number = Number(integer) + Number(fraction)
          return {
            given: number.toString(),
            expected: (Number(integer.toFixed(0)) + Number(expectedFraction)).toString(),
            actual: number.toFixed(fixLength)
          }
        })
    }
    로그인 후 복사

    <🎜 🎜> <<> 발견 <🎜

    이 오류에 세 부분이 포함되어 있습니다

    소수 부분의 마지막 중요한 숫자는 5이어야합니다 (.015 및 .01500은 동일한 결과를 생성).
    test({ fraction: .015, maxValue: 128 })
      .forEach(function(item) {
        console.log(item)
      })
    로그인 후 복사
    트림 길이는 단 하나의 소수 부분 만 줄여야합니다.

    다른 정수 값이 적용되면 오류가 일관되지 않게 발생합니다.

    일관성이 없습니까?

    예를 들어, 정수 1 ~ 128의 경우 (값) .tofixed (2)는 5로 끝나는 10 진수 자리를 사용하여 다음 결과를 초래합니다.

    .005에서 끝나는 꼬인 숫자는 항상 실패 (!!) .015에서 끝나는 꼬인 숫자는 1, 4 ~ 7, 128 .025로 끝나는 꼬인 숫자는 1, 2, 3에서 실패한 다음 16 ~ 63 .035로 끝나는 꼬인 숫자는 1에서 실패한 다음 32 ~ 128 .045로 끝나는 꼬인 숫자는 1 ~ 15로 실패한 다음 128 .055로 끝나는 꼬인 숫자는 1에서 1 번, 4 ~ 63 .065로 끝나는 꼬인 숫자는 1, 2, 3, 8 ~ 15, 32 ~ 128 에서 실패합니다. .075에서 끝나는 꼬인 숫자는 1, 8 ~ 31, 128 .085로 끝나는 꼬인 숫자는 1 ~ 7에서 실패한 다음 64 ~ 127 (!!) .095에서 끝나는 꼬인 숫자는 1, 4 ~ 7, 16 ~ 128

    내가하는 것보다 바이너리 및 플로팅 포인트 수학에 대해 더 많이 알고있는 사람들은 근본 원인을 유추 할 수 있습니다. 나는 이것을 운동으로 독자에게 맡깁니다. 고정 Tofixed ()

    에 의해 고정 된 값을 고정하려면 값을 고정시키는 것은 항상 올바르게 둥글다. (1.0151). 테스트와 폴리 필은 모두 정확성 검사를 위해이 지식을 사용합니다.

    이는 모든 tofixed () 구현에 간단한 수정이 있음을 의미합니다. 값에 소수점이 포함 된 경우 수정할 값의 문자열 버전의 끝에 "1"을 추가하십시오. 이는 "사양을 준수하지"않을 수 있지만, 이진 또는 부동 소수점 작업을 하위 레벨을 다시 방문하지 않고도 예상 결과를 얻을 수 있음을 의미합니다.
    • polyfill
    • 모든 구현이 수정되기 전에이 작업을 수행하려는 경우 (모든 사람이 원하지는 않음) 다음 PolyFill을 사용하여 Tofixed ()를 재정의 할 수 있습니다.
    • 그런 다음 테스트를 다시 실행하고 결과 길이가 0인지 확인하십시오.
    • 또는이 기사를 시작하는 초기 변환을 실행하십시오.
    • 읽어 주셔서 감사합니다!
    • JavaScript의 숫자에 대한 FAQS (FAQ) JavaScript에서 숫자 .tofixed () 메소드의 목적은 무엇입니까?

      JavaScript의 숫자 .tofixed () 메소드는 고정 점 표기법을 사용하여 숫자를 형식화하는 데 사용됩니다. 지수 표현을 사용하지 않고 소수점 이후에 지정된 숫자 수를 가진 숫자의 문자열 표현을 반환합니다. 필요한 경우 숫자가 둥글고 결과 문자열은 길이 후 소수점입니다. 숫자 .tofixed () 메소드가 때때로 부정확 한 결과를 제공하는 이유는 무엇입니까? JavaScript가 바이너리 플로팅 포인트 번호를 처리하는 방식으로 인해 숫자 .tofixed () 메소드는 때때로 부정확 한 결과를 제공합니다. JavaScript는 바이너리 플로팅 포인트 번호를 사용합니다. 이 부정확성은 숫자가 숫자 .tofixed () 메소드를 사용하여 특정 소수점 숫자로 반올림 될 때 예기치 않은 결과로 이어질 수 있습니다.

      숫자에서 반올림 오류를 수정하는 방법 .tofixed () 메소드?

      숫자에서 반올림 오류를 수정하는 한 가지 방법은 사용자 정의 반올림 함수를 사용하는 것입니다. 이 기능은 JavaScript의 디지털 처리의 특성을 고려하고보다 정확한 결과를 제공 할 수 있습니다. 예를 들어, 숫자를 10의 전력으로 곱하고 가장 가까운 정수로 반올림하는 함수를 사용하여 동일한 전력으로 나누어 줄 수 있습니다.

      숫자가 아닌 값으로 number.tofixed () 메소드를 사용할 수 있습니까?

      아니요, number.tofixed () 메소드는 숫자 값으로 만 사용할 수 있습니다. 수치가 아닌 값으로 사용하려고하면 JavaScript가 TypeError를 던집니다. 숫자가 아닐 수있는 값 으로이 메소드를 사용해야하는 경우 먼저 값이 숫자인지 확인해야합니다.

      숫자 .tofixed () 메소드와 기타 반올림 방법 사이에 성능 차이가 있습니까?

      숫자 .tofixed () 메소드를 사용하여 소수점 이하 20 개 이상으로 반올림 할 수 있습니까?

      아니요, number.tofixed () 메소드는 최대 20 개 자리로만 반올림 할 수 있습니다. 소수점 이하 20 개 이상으로 반올림하려고하면 JavaScript가 RangeError를 던집니다.

      음수를 다루는 방법?

      번호 .tofixed () 메소드는 양수를 다루는 것과 동일한 방식으로 음수를 처리합니다. 숫자의 절대 값을 지정된 소수점 자리 수로 반올림하고 음수 부호를 추가합니다.

      모든 JavaScript 환경에서 number.tofixed () 메소드를 사용할 수 있습니까?

      예, Number.tofixed () 메소드는 JavaScript의 표준 부분이며 모든 JavaScript 환경에서 사용할 수 있어야합니다. 그러나 다른 JavaScript 엔진이 숫자를 다르게 처리하기 때문에 모든 환경에서 결과가 정확히 동일하지 않을 수 있습니다.

      인수를 number.tofixed () 메소드에 전달하지 않으면 어떻게됩니까?

      인수를 number.tofixed () 메소드에 전달하지 않으면 기본적으로 10 진수 자리로 반올림됩니다. 이것은 숫자를 가장 가까운 정수로 반올림한다는 것을 의미합니다.

      많은 숫자로 number.tofixed () 메소드를 사용할 수 있습니까?

      예, 숫자 .tofixed () 메소드를 많은 숫자로 사용할 수 있습니다. 그러나 JavaScript는 최대 2^53 - 1의 숫자 만 정확하게 나타낼 수 있습니다. 이 숫자보다 숫자가 큰 Number.Tofixed () 메소드를 사용하려고하면 정확한 결과가 나오지 않을 수 있습니다.

    위 내용은 숫자 (). tofixed () 반올림 오류 : 깨지지 만 수정 가능의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿