Formatting floats without trailing zeros

后端 未结 18 1503
再見小時候
再見小時候 2020-11-22 10:03

How can I format a float so that it doesn\'t contain trailing zeros? In other words, I want the resulting string to be as short as possible.

For example:

<         


        
相关标签:
18条回答
  • 2020-11-22 10:25
    >>> str(a if a % 1 else int(a))
    
    0 讨论(0)
  • 2020-11-22 10:26

    After looking over answers to several similar questions, this seems to be the best solution for me:

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

    My reasoning:

    %g doesn't get rid of scientific notation.

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

    15 decimal places seems to avoid strange behavior and has plenty of precision for my needs.

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

    I could have used format(inputValue, '.15f'). instead of '%.15f' % inputValue, but that is a bit slower (~30%).

    I could have used Decimal(inputValue).normalize(), but this has a few issues as well. For one, it is A LOT slower (~11x). I also found that although it has pretty great precision, it still suffers from precision loss when using normalize().

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

    Most importantly, I would still be converting to Decimal from a float which can make you end up with something other than the number you put in there. I think Decimal works best when the arithmetic stays in Decimal and the Decimal is initialized with a string.

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

    I'm sure the precision issue of Decimal.normalize() can be adjusted to what is needed using context settings, but considering the already slow speed and not needing ridiculous precision and the fact that I'd still be converting from a float and losing precision anyway, I didn't think it was worth pursuing.

    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
    
    0 讨论(0)
  • 2020-11-22 10:31

    Here's the answer:

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

    output "3.14" and "3"

    trim='-' removes both the trailing zero's, and the decimal.

    0 讨论(0)
  • 2020-11-22 10:32

    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
    
    0 讨论(0)
  • 2020-11-22 10:33

    What about trying the easiest and probably most effective approach? The method normalize() removes all the rightmost trailing zeros.

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

    Works in Python 2 and Python 3.

    -- Updated --

    The only problem as @BobStein-VisiBone pointed out, is that numbers like 10, 100, 1000... will be displayed in exponential representation. This can be easily fixed using the following function instead:

    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()
    
    0 讨论(0)
  • 2020-11-22 10:33

    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

    0 讨论(0)
提交回复
热议问题