在Python中截断浮点数

时间:2009-04-23 22:56:44

标签: python floating-point

我想从浮点数中移除数字,使点后面有一个固定的位数,如:

1.923328437452 -> 1.923

我需要将字符串输出到另一个函数,而不是打印。

此外,我想忽略丢失的数字,而不是围绕它们。

30 个答案:

答案 0 :(得分:139)

round(1.923328437452, 3)

Python's documentation on the standard types。你需要向下滚动一下才能进入圆形函数。基本上第二个数字表示将它四舍五入到的小数位数。

答案 1 :(得分:102)

答案 2 :(得分:30)

round的结果是浮点数,所以请注意(示例来自Python 2.6):

>>> round(1.923328437452, 3)
1.923
>>> round(1.23456, 3)
1.2350000000000001

使用格式化字符串时,您会感觉更好:

>>> "%.3f" % 1.923328437452
'1.923'
>>> "%.3f" % 1.23456
'1.235'

答案 3 :(得分:18)

n = 1.923328437452
str(n)[:4]

答案 4 :(得分:11)

在我的Python 2.7提示符下:

>>> int(1.923328437452 * 1000)/1000.0 1.923

答案 5 :(得分:8)

def trunc(num, digits):
   sp = str(num).split('.')
   return '.'.join([sp[0], sp[1][:digits]])

这应该有效。它应该给你你正在寻找的截断。

答案 6 :(得分:8)

简单的python脚本 -

n = 1.923328437452
n = float(int(n * 1000))
n /=1000

答案 7 :(得分:8)

真正的pythonic方式是

from decimal import *

with localcontext() as ctx:
    ctx.rounding = ROUND_DOWN
    print Decimal('1.923328437452').quantize(Decimal('0.001'))

或更短:

from decimal import D, ROUND_DOWN

D('1.923328437452').quantize(D('0.001'), rounding=ROUND_DOWN)

<强>更新

通常问题不是截断浮动本身,而是在舍入之前不正确使用浮点数

例如:int(0.7*3*100)/100 == 2.09

如果你强制使用浮点数(比如说,你用numba加速你的代码),最好使用美分作为价格的“内部表示”:( {{ 1}})并对输入/输出进行乘法/除法。

答案 8 :(得分:7)

这个问题的答案很多都是完全错误的。它们要么将浮点数整齐(而不是截断),要么不适用于所有情况。

当我搜索Python truncate float&#39;这是一个非常简单的概念时,这是谷歌的最佳结果,值得更好的答案。我同意Hatchkins使用decimal模块是这样做的pythonic方式,因此我在这里给出了一个函数,我认为这个函数正确地回答了问题,并且在所有情况下都能正常工作。

作为旁注,通常,小数值不能用二进制浮点变量精确表示(有关此问题的讨论,请参阅here),这就是我的函数返回字符串的原因。

from decimal import Decimal, localcontext, ROUND_DOWN

def truncate(number, places):
    if not isinstance(places, int):
        raise ValueError("Decimal places must be an integer.")
    if places < 1:
        raise ValueError("Decimal places must be at least 1.")
    # If you want to truncate to 0 decimal places, just do int(number).

    with localcontext() as context:
        context.rounding = ROUND_DOWN
        exponent = Decimal(str(10 ** - places))
        return Decimal(str(number)).quantize(exponent).to_eng_string()

答案 9 :(得分:4)

我做了类似的事情:

from math import trunc


def truncate(number, decimals=0):
    if decimals < 0:
        raise ValueError('truncate received an invalid value of decimals ({})'.format(decimals))
    elif decimals == 0:
        return trunc(number)
    else:
        factor = float(10**decimals)
        return trunc(number*factor)/factor

答案 10 :(得分:4)

你可以这样做:

def truncate(f, n):
    return math.floor(f * 10 ** n) / 10 ** n

测试:

>>> f=1.923328437452
>>> [truncate(f, n) for n in range(5)]
[1.0, 1.9, 1.92, 1.923, 1.9233]

答案 11 :(得分:3)

如果您喜欢某些数学,那么这适用于+ ve数字:

>>> v = 1.923328437452
>>> v - v % 1e-3
1.923

答案 12 :(得分:1)

def precision(value, precision):
    """
    param: value: takes a float
    param: precision: int, number of decimal places
    returns a float
    """
    x = 10.0**precision
    num = int(value * x)/ x
    return num
precision(1.923328437452, 3)
  
    

1.923

  

答案 13 :(得分:1)

使用的一般而简单的功能:

def truncate_float(number, length):
    """Truncate float numbers, up to the number specified
    in length that must be an integer"""

    number = number * pow(10, length)
    number = int(number)
    number = float(number)
    number /= pow(10, length)
    return number

答案 14 :(得分:1)

使用numpy.round

import numpy as np
precision = 3
floats = [1.123123123, 2.321321321321]
new_float = np.round(floats, precision)

答案 15 :(得分:1)

这是一个简单的方法:

def truncate(num, res=3):
    return (floor(num*pow(10, res)+0.5))/pow(10, res)

对于num = 1.923328437452,输出1.923

答案 16 :(得分:1)

当使用pandas df时,这对我有用

import math
def truncate(number, digits) -> float:
    stepper = 10.0 ** digits
    return math.trunc(stepper * number) / stepper

df['trunc'] = df['float_val'].apply(lambda x: truncate(x,1))
df['trunc']=df['trunc'].map('{:.1f}'.format)

答案 17 :(得分:1)

INT(16.5); 这将给出16的整数值,即trunc,将无法指定小数,但猜猜你可以通过

来实现
import math;

def trunc(invalue, digits):
    return int(invalue*math.pow(10,digits))/math.pow(10,digits);

答案 18 :(得分:1)

只是想提一下旧的“make round()with floor()”技巧

round(f) = floor(f+0.5)
可以转动

从round()

制作floor()
floor(f) = round(f-0.5)

尽管这两条规则都是以负数为基础的,但使用它并不理想:

def trunc(f, n):
    if f > 0:
        return "%.*f" % (n, (f - 0.5*10**-n))
    elif f == 0:
        return "%.*f" % (n, f)
    elif f < 0:
        return "%.*f" % (n, (f + 0.5*10**-n))

答案 19 :(得分:1)

def trunc(f,n):
  return ('%.16f' % f)[:(n-16)]

答案 20 :(得分:0)

我认为大多数答案都太复杂了,这怎么办?

digits = 2  # Specify how many digits you want

fnum = '122.485221'
truncated_float = float(fnum[:fnum.find('.') + digits + 1])

>>> 122.48

仅扫描索引“。”。并根据需要截断(不舍入)。 将字符串转换为浮点数作为最后一步。

或者在您的情况下,如果您将float用作输入并希望将字符串作为输出:

fnum = str(122.485221)  # convert float to string first
truncated_float = fnum[:fnum.find('.') + digits + 1]  # string output

答案 21 :(得分:0)

简短易用的变体

def truncate_float(value, digits_after_point=2):
    pow_10 = 10 ** digits_after_point
    return (float(int(value * pow_10))) / pow_10

>>> truncate_float(1.14333, 2)
>>> 1.14

>>> truncate_float(1.14777, 2)
>>> 1.14


>>> truncate_float(1.14777, 4)
>>> 1.1477

答案 22 :(得分:0)

在我看来,here给出的核心思想是解决此问题的最佳方法。 不幸的是,它获得的票数较少,而拥有更多票数的later answer尚未完成(如评论中所述)。希望下面的实现为 截断 提供一个简短的 完整解决方案。

def trunc(num, digits):
    l = str(float(num)).split('.')
    digits = min(len(l[1]), digits)
    return (l[0]+'.'+l[1][:digits])

这应该处理在herehere中发现的所有极端情况。

答案 23 :(得分:0)

我认为更好的版本是找到小数点 index.,然后相应地取字符串切片:

def truncate(number, n_digits:int=1)->float:
    '''
    :param number: real number ℝ
    :param n_digits: Maximum number of digits after the decimal point after truncation
    :return: truncated floating point number with at least one digit after decimal point
    '''
    decimalIndex = str(number).find('.')
    if decimalIndex == -1:
        return float(number)
    else:
        return float(str(number)[:decimalIndex+n_digits+1])

答案 24 :(得分:0)

足够简单以适合列表理解,没有库或其他外部依赖项。对于Python> = 3.6,使用f字符串编写非常简单。

这个想法是让字符串转换将四舍五入到比您需要的地方更多的位置,然后将最后一位数字切掉。

>>> nout = 3  # desired number of digits in output
>>> [f'{x:.{nout+1}f}'[:-1] for x in [2/3, 4/5, 8/9, 9/8, 5/4, 3/2]]
['0.666', '0.800', '0.888', '1.125', '1.250', '1.500']

当然,这里有四舍五入(即四位数),但是在某些时候四舍五入 是不可避免的。如果截断和舍入之间的过渡是相关的,那么下面是一个更好的示例:

>>> nacc = 6  # desired accuracy (maximum 15!)
>>> nout = 3  # desired number of digits in output
>>> [f'{x:.{nacc}f}'[:-(nacc-nout)] for x in [2.9999, 2.99999, 2.999999, 2.9999999]]
>>> ['2.999', '2.999', '2.999', '3.000']

奖金:删除右侧的零

>>> nout = 3  # desired number of digits in output
>>> [f'{x:.{nout+1}f}'[:-1].rstrip('0') for x in [2/3, 4/5, 8/9, 9/8, 5/4, 3/2]]
['0.666', '0.8', '0.888', '1.125', '1.25', '1.5']

答案 25 :(得分:0)

在python 3中有一个简单的解决方法。在哪里剪切我使用帮助变量decPlace定义,以使其易于适应。

f = 1.12345
decPlace= 4
f_cut = int(f * 10**decPlace) /10**decPlace

输出:

f = 1.1234

希望它有所帮助。

答案 26 :(得分:0)

&gt;&gt;&gt; floor((1.23658945)* 10 ** 4)/ 10 ** 4
1.2365

除以10 **所需数字

答案 27 :(得分:-1)

# value  value to be truncated
# n  number of values after decimal

value = 0.999782
n = 3
float(int(value*1en))*1e-n

答案 28 :(得分:-1)

我也是一个蟒蛇新手,在这里使用了一些零碎的东西后,我提供了两美分

print str(int(time.time()))+str(datetime.now().microsecond)[:3]

str(int(time.time()))将时间epoch作为int并将其转换为字符串并与...连接 str(datetime.now()。microsecond)[:3]仅返回微秒,转换为字符串并截断为前3个字符

答案 29 :(得分:-3)

如果您的意思是打印时,则以下内容应该有效:

print '%.3f' % number