Programing

0으로 끝나지 않고 파이썬에서 부동 형식화

lottogame 2020. 6. 5. 08:02
반응형

0으로 끝나지 않고 파이썬에서 부동 형식화


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

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

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

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


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

'%g'%(3.140)

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

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

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

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


가장 쉽고 아마도 가장 효과적인 접근법을 시도하는 것은 어떻습니까? 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()

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

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

I'm not concerned with the possible "-0" result since -0.0 is a valid floating point number and it would probably be a rare occurrence anyway, but since you did mention you want to keep the string result as short as possible, you could always use an extra conditional at very little extra speed cost.

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

Here's a solution that worked for me. It's a blend of the solution by PolyMesh and use of the new .format() syntax.

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

Output:

3
3
3
3.1
3.14
3.14

You can simply use format() to achieve this:

format(3.140, '.10g') where 10 is the precision you want.


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

While formatting is likely that most Pythonic way, here is an alternate solution using the more_itertools.rstrip tool.

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"

The number is converted to a string, which is stripped of trailing characters that satisfy a predicate. The function definition fmt is not required, but it is used here to test assertions, which all pass. Note: it works on string inputs and accepts optional predicates.

See also details on this third-party library, more_itertools.


If you can live with 3. and 3.0 appearing as "3.0", a very simple approach that right-strips zeros from float representations:

print("%s"%3.140)

(thanks @ellimilial for pointing out the exceptions)


OP would like to remove superflouous zeros and make the resulting string as short as possible.

I find the %g exponential formatting shortens the resulting string for very large and very small values. The problem comes for values that don't need exponential notation, like 128.0, which is neither very large or very small.

Here is one way to format numbers as short strings that uses %g exponential notation only when Decimal.normalize creates strings that are too long. This might not be the fastest solution (since it does use 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']

For float you could use this:

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

Test it:

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

For Decimal see solution here: https://stackoverflow.com/a/42668598/5917543


Use %g with big enough width, for example '%.99g'. It will print in fixed-point notation for any reasonably big number.

EDIT: it doesn't work

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

You can use max() like this:

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


You can achieve that in most pythonic way like that:

python3:

"{:0.0f}".format(num)

Handling %f and you should put

%.2f

, where: .2f == .00 floats.

Example:

print "Price: %.2f" % prices[product]

output:

Price: 1.50

참고URL : https://stackoverflow.com/questions/2440692/formatting-floats-in-python-without-trailing-zeros

반응형