후행 0없이 부동 소수점 형식화


181

후행 0을 포함하지 않도록 float을 어떻게 포맷 할 수 있습니까? 즉, 결과 문자열을 가능한 짧게 만들고 싶습니다.

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

3 -> "3"
3. -> "3"
3.0 -> "3"
3.1 -> "3.1"
3.14 -> "3.14"
3.140 -> "3.14"

이 예는 전혀 의미가 없습니다. 3.14 == 3.140-그것들은 같은 부동 소수점 숫자입니다. 그 문제에 대해 3.140000은 동일한 부동 소수점 숫자입니다. 처음에는 0이 존재하지 않습니다.
S.Lott

33
@ S.Lott-문제는 두 숫자의 실제 동등성이 아니라 후행 0없이 부동 수를 인쇄하는 것입니다.
pokstad

1
@pokstad :이 경우 "불필요한"0은 없습니다. %0.2f그리고 %0.3f왼쪽의 마지막 번호를 생산하는 데 필요한 두 가지 형식입니다. %0.2f오른쪽에서 마지막 두 숫자를 생성하는 데 사용 합니다.
S.Lott

6
3.0 -> "3"여전히 유효한 사용 사례입니다. print( '{:,g}'.format( X )출력에 나를 위해 일한 때 내가의 출력있어 예상대로입니다. 3X = 6 / 2X = 5 / 22.5
ShoeMaker

1
오래된 질문이지만 .. print("%s"%3.140)당신이 원하는 것을 제공합니다. (아래에 답을 아래에 추가했습니다 ...)
drevicko

답변:


178

저도 할 것입니다 ('%f' % x).rstrip('0').rstrip('.')-과학적 표기법 등이 아닌 고정 소수점 형식을 보장합니다. 예, 매끄럽고 우아 %g하지는 않지만 작동합니다 %g. -).


6
그것의 유일한 문제는 결국 '%.2f' % -0.0001당신을 떠날 것입니다 . -0.00-0
Kos

3
기본 정밀도가 6이기 때문에 @ alexanderlukanin13 참조 docs.python.org/2/library/string.html : 'f' Fixed point. Displays the number as a fixed-point number. The default precision is 6.당신은 위의 솔루션에서 '% 0.7f'를 사용해야합니다.
derenio

3
@derenio 좋은 지적 :-) 이상한 일 이 일어나기 시작하기 '%0.15f'때문에 위의 정밀도를 높이는 것은 나쁜 생각 이라고 덧붙일 수 있습니다 .
alexanderlukanin13

1
다른 줄의 중간에있는 경우 : print('In the middle {} and something else'.format('{:f}'.format(a).rstrip('0')))
내결함성

1
@Alex Martelli, double rstrip명령을 제거하십시오 . 대신 .한 번의 작업으로 점 ( )과 후행 0을 모두 제거하려면 간단히 이것을 사용하십시오 .('%f' % x).rstrip('.0')
Gabriel Staples

143

%g이것을 달성하기 위해 사용할 수 있습니다 :

'%g'%(3.140)

또는 파이썬 2.6 이상의 경우 :

'{0:g}'.format(3.140)

보내는 사람 에 대한 문서format : g(무엇보다도) 원인

중요하지 않은 후행 0은 [유의]에서 제거되며 그 뒤에 남은 자릿수가 없으면 소수점도 제거됩니다.


28
아 거의! 때로는 과학적 표기법 ( "2.342E + 09")으로 부동 소수점을 형식화합니다.이를 끌 수 있습니까, 즉 항상 모든 유효 숫자를 표시합니까?
TarGz

5
왜 사용 '{0:...}'.format(value)당신이 사용할 수있을 때 format(value, '...')? 따라서 비어있는 템플릿 문자열에서 형식 지정자를 구문 분석하지 않아도됩니다.
Martijn Pieters

2
@MartijnPieters : 형식 지정자를 파싱하는 데 드는 최소 비용은 다른 오버 헤드 AFAICT에 의해 늪이됩니다. 실제로 3.6에 대한 로컬 벤치 마크 (실제 코드를 정확하게 모델링하기 위해 마이크로 벤치 마크의 기능 범위 지정)는 format(v, '2.5f')~보다 10 % 더 오래 걸렸습니다 '{:2.5f}'.format(v). 그렇지 않은 경우에도 str메소드 양식 을 사용하는 경향이 있습니다. 왜냐하면 조정해야 할 때, 값을 추가하는 등의 변경이 적기 때문입니다. 물론 3.6에서 우리는 대부분의 목적을 위해 f- 문자열을 가지고 있습니다. :-)
ShadowRanger

5
Python 3.6에서는 float 변수가있는 f"{var:g}"위치 로 단축 할 수 있습니다 var.
TheGreatCabbage

12

가장 쉽고 아마도 가장 효과적인 접근법을 시도하는 것은 어떻습니까? normalize () 메소드 는 가장 오른쪽에있는 모든 0을 제거합니다.

from decimal import Decimal

print (Decimal('0.001000').normalize())
# Result: 0.001

Python 2Python 3 에서 작동합니다 .

-업데이트-

@ BobStein-VisiBone이 지적한 유일한 문제는 10, 100, 1000 ...과 같은 숫자가 지수 표현으로 표시된다는 것입니다. 대신 다음 기능을 사용하여 쉽게 고칠 수 있습니다.

from decimal import Decimal


def format_float(f):
    d = Decimal(str(f));
    return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()

2
를 제외하고는 Decimal('10.0').normalize()된다'1E+1'
밥 스타

11

몇 가지 유사한 질문에 대한 답변을 살펴본 후에 이것은 가장 좋은 해결책 인 것 같습니다.

def floatToString(inputValue):
    return ('%.15f' % inputValue).rstrip('0').rstrip('.')

내 추론 :

%g 과학적 표기법을 제거하지 않습니다.

>>> '%g' % 0.000035
'3.5e-05'

소수 자릿수 15 자리는 이상한 행동을 피하는 것으로 보이며 내 요구에 충분한 정밀도를 가지고 있습니다.

>>> ('%.15f' % 1.35).rstrip('0').rstrip('.')
'1.35'
>>> ('%.16f' % 1.35).rstrip('0').rstrip('.')
'1.3500000000000001'

format(inputValue, '.15f').대신 사용할 수는 '%.15f' % inputValue있지만 조금 느립니다 (~ 30 %).

사용할 수는 Decimal(inputValue).normalize()있지만 몇 가지 문제가 있습니다. 하나, 그것은 훨씬 더 느립니다 (~ 11x). 또한 정확도가 매우 뛰어나지 만 사용할 때 여전히 정밀도 손실이 발생한다는 것을 알았습니다 normalize().

>>> Decimal('0.21000000000000000000000000006').normalize()
Decimal('0.2100000000000000000000000001')
>>> Decimal('0.21000000000000000000000000006')
Decimal('0.21000000000000000000000000006')

가장 중요한 것은, 나는 여전히 당신이 거기에 넣은 숫자가 아닌 다른 것으로 끝날 수있는 Decimal에서 로 변환 할 float것입니다. 내가 생각하는 Decimal일을 가장 잘 할 때 산술에서 숙박 Decimal하고이 Decimal문자열로 초기화됩니다.

>>> Decimal(1.35)
Decimal('1.350000000000000088817841970012523233890533447265625')
>>> Decimal('1.35')
Decimal('1.35')

Decimal.normalize()컨텍스트 설정을 사용하여 필요한 것에 대한 정밀도 문제를 조정할 수 있다고 확신 하지만 이미 느린 속도와 어리석은 정밀도가 필요하지 않고 여전히 부동에서 변환하고 정밀도를 잃어 가고 있다는 사실을 고려하면 추구 할 가치가 있다고 생각하지 않습니다.

-0.0이 유효한 부동 소수점 수이므로 가능한 "-0"결과에 대해 걱정하지 않고 어쨌든 드물게 발생하지만 문자열 결과를 가능한 한 짧게 유지하려고합니다. 아주 작은 추가 비용으로 항상 추가 조건을 사용할 수 있습니다.

def floatToString(inputValue):
    result = ('%.15f' % inputValue).rstrip('0').rstrip('.')
    return '0' if result == '-0' else result

1
불행히도 소수점 이하 자릿수 왼쪽에 5 자리 이상의 숫자 만 사용할 수 있습니다. 예를 들어 floatToString(12345.6)반환 '12345.600000000000364'합니다. %.15f이 예 에서는 15를 더 작은 숫자로 줄이면 문제가 해결되지만 숫자가 클수록 그 값은 점점 더 낮아져 야합니다. 숫자의 log-base-10을 기반으로 동적으로 계산할 수는 있지만 빠르게 복잡해집니다.
JohnSpeeks

1
이 문제를 해결하는 한 가지 방법은 소수점 이하 자릿수가 아닌 정수의 길이를 제한하는 것입니다.result = ('%15f' % val).rstrip('0').rstrip('.').lstrip(' ')
Timothy Smith

@ JohnSpeeks 나는 이것이 피할 수 있는지 확실하지 않습니다. 왼쪽에 더 많은 숫자가 필요한 경우 부동 숫자가 정확도를 나타내지 못하는 부작용입니다. 내가 알 수 있듯이 문자열로 나오는 숫자는 부동 소수점으로 들어가는 숫자와 같거나 적어도 가장 가까운 표현입니다. >>>12345.600000000000364 == 12345.6 True
PolyMesh

나는 또 다른 해결책을 썼다 .
niitsuma

8

나를 위해 일한 해결책이 있습니다. 그것은의 혼합의 솔루션 으로 폴리 메쉬 새로운의 사용 .format() 구문 .

for num in 3, 3., 3.0, 3.1, 3.14, 3.140:
    print('{0:.2f}'.format(num).rstrip('0').rstrip('.'))

출력 :

3
3
3
3.1
3.14
3.14

이것의 잘못된 점은 합리적인 수의 십진수를 설정해야한다는 것입니다. 설정할수록 숫자를 더 정확하게 표현할 수 있지만이 작업을 많이 수행하면 성능이 저하 될 수 있습니다.
beruic

1
beruic의 의견에 덧붙여, 이것은 하드 코딩 된 3.141것처럼 더 정밀한 수레 (예 :)에는 작동하지 않습니다 .2f.
TrebledJ

3

format ()을 사용하여 이것을 달성 할 수 있습니다.

format(3.140, '.10g') 여기서 10은 원하는 정밀도입니다.


2
>>> str(a if a % 1 else int(a))

당신은 의미하지 int(a) if a % 1 else a않습니까?
beruic 2016 년

Beruic님께, 답변은 부정적인 답변입니다. a if a % 1 else int(a)맞다. 질문은 문자열로 출력해야하므로 방금 추가했습니다.str
Shameem

아, 이제 알겠다 a % 10이 아니기 때문에 진실입니다. 나는 그것을 암묵적으로 잘못 인식했다 a % 1 == 0.
beruic 2016 년

2

서식은 대부분 Pythonic 방식이지만, 다음은이 more_itertools.rstrip도구를 사용하는 대체 솔루션 입니다.

import more_itertools as mit


def fmt(num, pred=None):
    iterable = str(num)
    predicate = pred if pred is not None else lambda x: x in {".", "0"}
    return "".join(mit.rstrip(iterable, predicate))

assert fmt(3) == "3"
assert fmt(3.) == "3"
assert fmt(3.0) == "3"
assert fmt(3.1) == "3.1"
assert fmt(3.14) == "3.14"
assert fmt(3.140) == "3.14"
assert fmt(3.14000) == "3.14"
assert fmt("3,0", pred=lambda x: x in set(",0")) == "3"

숫자는 문자열로 변환되며 술어를 만족시키는 후행 문자가 제거됩니다. 함수 정의 fmt는 필요하지 않지만 여기서는 어설 션을 테스트하는 데 사용됩니다. 참고 : 문자열 입력에서 작동하며 선택적 술어를 허용합니다.

이 타사 라이브러리에 대한 자세한 내용도 참조하십시오 more_itertools.


1

"3.0"으로 표시되는 3. 및 3.0으로 살 수 있다면 부동 소수점 표현에서 0을 오른쪽으로 벗기는 매우 간단한 방법입니다.

print("%s"%3.140)

(예외를 지적한 @ellimilial 덕분에)


1
그러나 print("%s"%3.0)그렇습니다.
ellimilial

1

QuantiPhy 패키지 사용은 옵션입니다. 일반적으로 QuantiPhy는 단위 및 SI 스케일 팩터가있는 숫자로 작업 할 때 사용되지만 다양한 숫자 형식 옵션이 있습니다.

    >>> from quantiphy import Quantity

    >>> cases = '3 3. 3.0 3.1 3.14 3.140 3.14000'.split()
    >>> for case in cases:
    ...    q = Quantity(case)
    ...    print(f'{case:>7} -> {q:p}')
          3 -> 3
         3. -> 3
        3.0 -> 3
        3.1 -> 3.1
       3.14 -> 3.14
      3.140 -> 3.14
    3.14000 -> 3.14

이 상황에서는 전자 표기법을 사용하지 않습니다.

    >>> cases = '3.14e-9 3.14 3.14e9'.split()
    >>> for case in cases:
    ...    q = Quantity(case)
    ...    print(f'{case:>7} -> {q:,p}')
    3.14e-9 -> 0
       3.14 -> 3.14
     3.14e9 -> 3,140,000,000

선호하는 대안은 SI 스케일 팩터를 사용하는 것입니다.

    >>> cases = '3e-9 3.14e-9 3 3.14 3e9 3.14e9'.split()
    >>> for case in cases:
    ...    q = Quantity(case, 'm')
    ...    print(f'{case:>7} -> {q}')
       3e-9 -> 3 nm
    3.14e-9 -> 3.14 nm
          3 -> 3 m
       3.14 -> 3.14 m
        3e9 -> 3 Gm
     3.14e9 -> 3.14 Gm

0

OP는 과잉 영점을 제거하고 결과 문자열을 가능한 짧게 만들고 싶습니다.

% g 지수 형식은 결과 문자열을 매우 크고 아주 작은 값으로 줄입니다. 128.0과 같이 지수 표기법이 필요하지 않은 값은 크거나 작지 않습니다.

다음은 Decimal.normalize가 너무 긴 문자열을 생성 할 때만 % g 지수 표기법을 사용하는 짧은 문자열로 숫자를 형식화하는 한 가지 방법입니다. Decimal.normalize를 사용하므로 가장 빠른 솔루션이 아닐 수도 있습니다.

def floatToString (inputValue, precision = 3):
    rc = str(Decimal(inputValue).normalize())
    if 'E' in rc or len(rc) > 5:
        rc = '{0:.{1}g}'.format(inputValue, precision)        
    return rc

inputs = [128.0, 32768.0, 65536, 65536 * 2, 31.5, 1.000, 10.0]

outputs = [floatToString(i) for i in inputs]

print(outputs)

# ['128', '32768', '65536', '1.31e+05', '31.5', '1', '10']

0

float의 경우 다음을 사용할 수 있습니다.

def format_float(num):
    return ('%i' if num == int(num) else '%s') % num

그것을 테스트하십시오 :

>>> format_float(1.00000)
'1'
>>> format_float(1.1234567890000000000)
'1.123456789'

Decimal의 경우 솔루션을 참조하십시오 : https : //.com/a/42668598/5917543


0

"{:.5g}".format(x)

이것을 사용하여 부동 소수점을 0으로 추적합니다.


3143.93-> 3.1e + 03
j35t3r

0

대답은 다음과 같습니다.

import numpy

num1 = 3.1400
num2 = 3.000
numpy.format_float_positional(num1, 3, trim='-')
numpy.format_float_positional(num2, 3, trim='-')

"3.14"및 "3"출력

trim='-' 후행 0과 소수를 모두 제거합니다.


-1

너비가 충분히 큰 % g를 사용하십시오 (예 : '% .99g'). 합리적으로 많은 수의 고정 소수점 표기법으로 인쇄됩니다.

편집 : 작동하지 않습니다

>>> '%.99g' % 0.0000001
'9.99999999999999954748111825886258685613938723690807819366455078125e-08'

1
.99너비가 아닌 정밀도입니다. 다소 유용하지만 직접 정밀도를이 방법으로 설정할 수는 없습니다 (자신을 잘라내는 것 제외).
Kos

-1

다음 max()과 같이 사용할 수 있습니다 :

print(max(int(x), x))


1
x부정적인 경우를 고려해야합니다 . if x < 0: print(min(x), x) else : print(max(x), x)
ThunderPhoenix

json stringify를하고 싶을 때 유용한 방법입니다. float 1.0은 int 1로 변경되므로 자바 스크립트와 동일하게 수행됩니다.
pingze


-4

% f를 다루면

% .2f

.2f == .00 수레.

예:

"가격 : % .2f"가격 % 인쇄 [제품]

산출:

가격 : 1.50


1
이것은 질문이 원하는 것이 아니라는 것이 분명하게 언급되어 있습니다. 공감해야합니다.
episodeyang
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.