development

소수점 x 자리로 반올림?

big-blog 2020. 11. 29. 11:58
반응형

소수점 x 자리로 반올림?


파이썬 부동 소수점을 x 소수로 반올림하는 방법이 있습니까? 예를 들면 :

>>> x = roundfloat(66.66666666666, 4)
66.6667
>>>x = roundfloat(1.29578293, 6)
1.295783

나는 그들을 자르거나 자르는 방법을 찾았지만 (66.666666666-> 66.6666), 둥글지는 않습니다 (66.666666666-> 66.6667).


내장 기능 사용 round():

In [23]: round(66.66666666666,4)
Out[23]: 66.6667

In [24]: round(1.29578293,6)
Out[24]: 1.295783

에 대한 도움말 round():

round (number [, ndigits])-> 부동 소수점 수

숫자를 10 진수로 지정된 정밀도로 반올림합니다 (기본값 0 자리). 이것은 항상 부동 소수점 숫자를 반환합니다. 정밀도는 음수 일 수 있습니다.


나는 Ashwini Chaudhary의 대답에 대위법을 제공해야한다고 느낍니다. 외관에도 불구하고 round함수 의 두 인수 형식은 Python float를 주어진 소수 자릿수로 반올림 하지 않으며 , 생각할 때도 원하는 솔루션이 아닌 경우가 많습니다. 설명하겠습니다 ...

(Python) 부동 소수점을 소수점 이하 자릿수로 반올림하는 기능은 자주 요청되는 기능이지만 실제로 필요한 것은 거의 없습니다. 유쾌하고 간단한 대답 round(x, number_of_places)은 매력적인 성가신 것입니다. 원하는 것을 수행하는 것처럼 보이지만 Python 수레가 내부적으로 바이너리로 저장되어 있기 때문에 다소 미묘한 작업을 수행하고 있습니다. 다음 예를 고려하십시오.

>>> round(52.15, 1)
52.1

무엇 순진한 이해를 바탕으로 round수행이 잘못 같습니다 확실히는 반올림해야 최대52.2하기보다는 아래52.1? 이러한 동작을 신뢰할 수없는 이유를 이해하려면 이것이 단순한 10 진수에서 10 진수로의 연산처럼 보이지만 단순한 것과는 거리가 멀다는 점을 이해해야합니다.

따라서 위의 예에서 실제로 일어나는 일이 있습니다. ( 심호흡 ) 우리는 표시하고 소수 가장 가까운 표현 바이너리 가장 가까운 부동 소수점 숫자를 n-digits - 후 - 더 - 포인트 진수 A를 수 바이너리 로 작성된 숫자 리터의 부동 소수점 근사치 진수 . 따라서 원래 숫자 리터럴에서 표시된 출력으로 가져 오기 위해 기본 기계는 2 진 및 10 진수 형식간에 각 방향으로 2 개씩 4 개의 개별 변환을 수행했습니다. 분석 (그리고 IEEE 754 binary64 형식, 반올림-짝수 반올림 및 IEEE 754 규칙 가정에 대한 일반적인 고지 사항 포함) :

  1. 먼저 숫자 리터럴 52.15이 구문 분석되어 Python float로 변환됩니다. 저장된 실제 숫자는 7339460017730355 * 2**-47, 또는 52.14999999999999857891452847979962825775146484375입니다.

  2. 내부적으로 round연산 의 첫 번째 단계로 Python은 저장된 숫자에 가장 가까운 소수점 이하 1 자리 십진수 문자열을 계산합니다. 저장된 숫자는 원래 값인의 터치이므로 52.15결국 반올림하여 문자열을 얻습니다 52.1. 이것은 우리가 52.1대신 최종 출력으로 얻는 이유를 설명합니다 52.2.

  3. 그런 다음 round작업 의 두 번째 단계 에서 Python은 해당 문자열을 다시 부동 소수점으로 변환하여 가장 가까운 이진 부동 소수점 숫자를 52.1, 즉 7332423143312589 * 2**-47, 또는 52.10000000000000142108547152020037174224853515625.

  4. 마지막으로 Python의 읽기 평가 인쇄 루프 (REPL)의 일부로 부동 소수점 값이 표시됩니다 (10 진수). 여기에는 이진 값을 다시 10 진수 문자열로 변환 52.1하여 최종 출력으로 가져 옵니다.

Python 2.7 이상에서는 3 단계와 4 단계의 두 변환이 서로를 취소하는 즐거운 상황이 있습니다. 이는 Python이 선택한 repr구현 으로 인해 실제 float로 올바르게 반올림되도록 보장되는 가장 짧은 십진수 값을 생성합니다. 이 선택의 결과 중 하나는 유효 숫자가 15 개 이하인 10 진수 리터럴 (너무 크지 않고 너무 작지 않음)으로 시작하면 정확히 동일한 숫자를 표시하는 해당 부동 소수점이 표시된다는 것입니다.

>>> x = 15.34509809234
>>> x
15.34509809234

불행히도 이것은 파이썬이 십진수로 값을 저장하고 있다는 착각을 불러 일으 킵니다. 하지만 파이썬 2.6에서는 그렇지 않습니다! 다음은 Python 2.6에서 실행 된 원래 예제입니다.

>>> round(52.15, 1)
52.200000000000003

52.2대신 반대 방향으로 반올림 할뿐만 아니라 52.1표시된 값도 52.2! 이 동작으로 인해 "round is broken!"줄을 따라 Python 버그 추적기에 수많은보고가 발생했습니다. 그러나 그것은 round망가진 것이 아니라 사용자의 기대입니다. (좋아, 좋아, roundA는 약간 은 정확한 반올림을 사용하지 않는 점에서, 파이썬 2.6에서 깨진 비트.)

짧은 버전 : 두 개의 인수 라운드를 사용하고, 그리고 당신은에서 예측 가능한 행동을 기대하는 경우 바이너리 A와 근사 진수 (A)의 라운드 A와 근사 진수 중간 케이스를, 당신은 사서 고생하고 있습니다.

따라서 "두 인수 라운드는 나쁘다"라는 주장으로 충분합니다. 대신 무엇을 사용해야 합니까? 수행하려는 작업에 따라 몇 가지 가능성이 있습니다.

  • 표시 목적으로 반올림하는 경우 부동 결과를 전혀 원하지 않습니다. 당신은 문자열을 원합니다. 이 경우 대답은 문자열 형식을 사용하는 것입니다.

    >>> format(66.66666666666, '.4f')
    '66.6667'
    >>> format(1.29578293, '.6f')
    '1.295783'
    

    그럼에도 불구하고, 명백한 십진법 중간 케이스의 동작에 놀라지 않으려면 내부 이진 표현을 알아야합니다.

    >>> format(52.15, '.1f')
    '52.1'
    
  • If you're operating in a context where it matters which direction decimal halfway cases are rounded (for example, in some financial contexts), you might want to represent your numbers using the Decimal type. Doing a decimal round on the Decimal type makes a lot more sense than on a binary type (equally, rounding to a fixed number of binary places makes perfect sense on a binary type). Moreover, the decimal module gives you better control of the rounding mode. In Python 3, round does the job directly. In Python 2, you need the quantize method.

    >>> Decimal('66.66666666666').quantize(Decimal('1e-4'))
    Decimal('66.6667')
    >>> Decimal('1.29578293').quantize(Decimal('1e-6'))
    Decimal('1.295783')
    
  • In rare cases, the two-argument version of round really is what you want: perhaps you're binning floats into bins of size 0.01, and you don't particularly care which way border cases go. However, these cases are rare, and it's difficult to justify the existence of the two-argument version of the round builtin based on those cases alone.

참고URL : https://stackoverflow.com/questions/13479163/round-float-to-x-decimals

반응형