在Python中截断为三个小数


72

我如何获得1324343032.324?

如您在下面看到的,以下内容不起作用:

>>1324343032.324325235 * 1000 / 1000
1324343032.3243253
>>int(1324343032.324325235 * 1000) / 1000.0
1324343032.3239999
>>round(int(1324343032.324325235 * 1000) / 1000.0,3)
1324343032.3239999
>>str(1324343032.3239999)
'1324343032.32'

4
集合中没有用浮点数表示的值。
— Karl Knechtel

2
如果Karl的注释不够清楚:二进制浮点数中没有1324343032.324这样的数字。如果切换到更高版本的Python(2.7或3.1或更高版本),解释器将为您显示1324343032.324。但是实际上,无论使用哪个Python版本,您要使用的数字既不是1324343032.324也不是1324343032.3239999。准确获取1324343032.324的唯一方法是使用decimal模块或其他任意精度的数学库,例如gmpy。
— 约翰Y

如果您想四舍五入到给定的小数位数,则下面接受的答案是正确的。但是,问题在问,我想知道的是如何截断到特定的小数位数。对我来说,'%.3f'%(1324343032.3243)并'%.3f'%(1324343032.3245)给出不同的结果。(我正在使用Python 2.7.8)。
— nullstellensatz


1
@AbhranilDas这个问题与您所指出的重复。由于这两个问题的答案都具有误导性,因此我将此问题标记为重复,因此所有与截断有关的问题都可以在一个地方处理。另外,请查看我对原始问题的评论和建议的答案。
— nullstellensatz 2015年

Answers:


78

float()如果要将其保存为,可以在其周围使用其他内容float。

%.3f'%(1324343032.324325235)

4
这基本上是正确的答案,只需使用val = '%.3f'%(1324343032.324325235)代替即可print。
— David H. Clements,

14
如果您要舍入(舍入)给定的小数位数,则此答案是正确的。但是,问题在问,我想知道的是如何截断到特定的小数位数。对我来说,'%.3f'%(1324343032.3243)并'%.3f'%(1324343032.3245)给出不同的结果。(我正在使用Python 2.7.8)。
— nullstellensatz

3
'%.2f'%8866.316是圆形但不截断
— Oleg

2
你四舍五入; 看一下我的答案
— matsib.dev,

3
这不是截断。
— Darkenor

53

您可以使用以下函数将数字截断为设定的小数位数:

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

用法:

>>> truncate(1324343032.324325235, 3)
1324343032.324

9
这确实应该是公认的答案。该代码简单,优雅,并且最有意义。使用标准的截断功能,但是首先将小数点后移,执行完截断后再将小数点后移。
— CatalystNZ

注意浮点精度错误truncate(-1.13, 2) == -1.12,我将其更改了一点(口中有苦味)至math.trunc(round(stepper * number, digits * 3)) / stepper
— eplaut

您可以做int(stepper * number)/ stepper
— Yohan E

16

我找到了另一个解决方案(它必须比“字符串巫术”变通办法更有效):

>>> import decimal
# By default rounding setting in python is decimal.ROUND_HALF_EVEN
>>> decimal.getcontext().rounding = decimal.ROUND_DOWN
>>> c = decimal.Decimal(34.1499123)
# By default it should return 34.15 due to '99' after '34.14'
>>> round(c,2)
Decimal('34.14')
>>> float(round(c,2))
34.14
>>> print(round(c,2))
34.14

关于小数模块

关于舍入设置


1
我认为这应该是更受欢迎的答案之一...它教您如何利用和修改模块以发挥自己的优势,它表达了Python真正的动态和强大功能
— 温室

8

这个怎么样:

In [1]: '%.3f' % round(1324343032.324325235 * 1000 / 1000,3)
Out[1]: '1324343032.324'

Python中round()的可能重复似乎没有正确舍入

[编辑]

考虑到其他评论,我相信您会想要做的:

In : Decimal('%.3f' % (1324343032.324325235 * 1000 / 1000))
Out: Decimal('1324343032.324')

浮点精度将不是您想要的:

In : 3.324
Out: 3.3239999999999998

(所有示例均适用于Python 2.6.5)


7

'%.3f'%(1324343032.324325235)

在这种情况下也可以。

只需稍微更改一下数字:

1324343032.324 7 25235

接着:

'%.3f'%(1324343032.324725235)

给你 1324343032.325

尝试以下方法:

def trun_n_d(n,d):
    s=repr(n).split('.')
    if (len(s)==1):
        return int(s[0])
    return float(s[0]+'.'+s[1][:d])

trun_n_d的另一个选项:

def trun_n_d(n,d):
    dp = repr(n).find('.') #dot position
    if dp == -1:  
        return int(n) 
    return float(repr(n)[:dp+d+1])

又一选项(一oneliner为一个)trun_n_d [此,假设“ Ñ ”是一个STR和“ d ”由INT ]:

def trun_n_d(n,d):
    return (  n if not n.find('.')+1 else n[:n.find('.')+d+1]  )

trun_n_d在Python 2.7和Python 3.6中都提供了所需的输出

trun_n_d(1324343032.324325235,3)返回1324343032.324

同样,trun_n_d(1324343032.324 7 25235,3)返回1324343032.324


注意1在Python 3.6(以及可能在Python 3.x中)可以正常工作:

def trun_n_d(n,d):
    return int(n*10**d)/10**d

但是,以这种方式,四舍五入的鬼总是潜伏着。

注意2在这种情况下,由于python的数字内部,例如舍入和缺乏精度,将n作为str使用比使用int对应要好得多;您总是可以将数字最后转换为浮点数。


6

使用十进制模块。但是,如果您必须使用浮点数,并且仍然以某种方式将其强制转换为给定数目的小数点,则将其转换为字符串后退可提供一种(相当笨拙,恐怕)这样做的方法。

>>> q = 1324343032.324325235 * 1000 / 1000
>>> a = "%.3f" % q
>>> a
'1324343032.324'
>>> b = float(a)
>>> b
1324343032.324

所以:

float("%3.f" % q)

1
最好先提到十进制模块,因为这是唯一完全正确的答案。其余部分需要注意的一件事是,b在您的示例中,在2.7之前的Python版本上,该代码将显示为1324343032.3239999。实际上,这就是OP在尝试时所看到的价值。当然,就二进制浮点而言,这两个值是无法区分的。
— 约翰Y

5

我相信使用该format功能不是一个好主意。请看下面。取整值。我使用Python 3.6。

>>> '%.3f'%(1.9999999)
'2.000'

改用正则表达式:

>>> re.match(r'\d+.\d{3}', str(1.999999)).group(0)
'1.999'


2

也许这样:

def myTrunc(theNumber, theDigits):

    myDigits = 10 ** theDigits
    return (int(theNumber * myDigits) / myDigits)

请注意,由于工作方式的变化,这在Python 3上有效,但在Python 2上无效/。
— 杰夫·G

2

好的,这只是另一种解决方法,可以将数字作为字符串处理并对其执行简单的操作。这将为您提供数字的截断输出,而不是四舍五入的数字。

num = str(1324343032.324325235)
i = num.index(".")
truncated = num[:i + 4]
    
print(truncated)

输出:

'1324343032.324'

当然,您可以解析:

float(truncated)

1

在寻找解决此问题的方法之后,无需加载任何Python 3模块或额外的数学运算,我仅使用str.format()e .float()解决了该问题。我认为这种方式比使用其他数学运算(例如最常用的解决方案)更快。我需要一个快速的解决方案,因为我使用非常大的数据集,因此在这里可以很好地工作。

def truncate_number(f_number, n_decimals):
      strFormNum = "{0:." + str(n_decimals+5) + "f}"
      trunc_num = float(strFormNum.format(f_number)[:-5])
      return(trunc_num)

# Testing the 'trunc_num()' function
test_num = 1150/252
[(idx, truncate_number(test_num, idx)) for idx in range(0, 20)]

它返回以下输出:

[(0, 4.0),
 (1, 4.5),
 (2, 4.56),
 (3, 4.563),
 (4, 4.5634),
 (5, 4.56349),
 (6, 4.563492),
 (7, 4.563492),
 (8, 4.56349206),
 (9, 4.563492063),
 (10, 4.5634920634),
 (11, 4.56349206349),
 (12, 4.563492063492),
 (13, 4.563492063492),
 (14, 4.56349206349206),
 (15, 4.563492063492063),
 (16, 4.563492063492063),
 (17, 4.563492063492063),
 (18, 4.563492063492063),
 (19, 4.563492063492063)]

0

您还可以使用:

import math

nValeur = format(float(input('Quelle valeur ?    ')), '.3f')

在Python 3.6中,它将起作用。


0
a = 1.0123456789
dec = 3 # keep this many decimals
p = 10 # raise 10 to this power
a * 10 ** p // 10 ** (p - dec) / 10 ** dec
>>> 1.012

0

我认为最好和正确的方法是使用decimal模块。

import decimal

a = 1324343032.324325235

decimal_val = decimal.Decimal(str(a)).quantize(
   decimal.Decimal('.001'), 
   rounding=decimal.ROUND_DOWN
)
float_val = float(decimal_val)

print(decimal_val)
>>>1324343032.324

print(float_val)
>>>1324343032.324

您可以使用不同的值rounding=decimal.ROUND_DOWN,可用的选项包括ROUND_CEILING,ROUND_DOWN,ROUND_FLOOR,ROUND_HALF_DOWN,ROUND_HALF_EVEN,ROUND_HALF_UP,ROUND_UP,和ROUND_05UP。您可以在docs中找到每个选项的说明。


0

自从这个问题以来,也许python发生了变化,以下所有内容似乎都运行良好

Python2.7

int(1324343032.324325235 * 1000) / 1000.0
float(int(1324343032.324325235 * 1000)) / 1000
round(int(1324343032.324325235 * 1000) / 1000.0,3)
# result for all of the above is 1324343032.324

0

我建议下一个解决方案:

def my_floor(num, precision):
   return f'{num:.{precision+1}f}'[:-1]

my_floor(1.026456,2) # 1.02


0

我正在尝试生成5到7之间的随机数,并希望将其限制为3个小数位。

import random

num = float('%.3f' % random.uniform(5, 7))
print (num)

0

功能

def truncate(number: float, digits: int) -> float:
    pow10 = 10 ** digits
    return number * pow10 // 1 / pow10

测试码

f1 = 1.2666666
f2 = truncate(f1, 3)
print(f1, f2)

输出量

1.2666666 1.266

说明

它将f1数字digits向左移动,然后切掉所有小数,最后将数字digits向右移动。

顺序示例:

1.2666666 # number
1266.6666 # number * pow10
1266.0    # number * pow10 // 1
1.266     # number * pow10 // 1 / pow10

0

我开发了一个很好的解决方案,我知道有很多If说法,但是它有效!(仅适用于<1个数字)

def truncate(number, digits) -> float:
    startCounting = False
    if number < 1:
      number_str = str('{:.20f}'.format(number))
      resp = ''
      count_digits = 0
      for i in range(0, len(number_str)):
        if number_str[i] != '0' and number_str[i] != '.' and number_str[i] != ',':
          startCounting = True
        if startCounting:
          count_digits = count_digits + 1
        resp = resp + number_str[i]
        if count_digits == digits:
            break
      return resp
    else:
      return number

-1
>>> float(1324343032.324325235) * float(1000) / float(1000)

1324343032.3243253

>>> round(float(1324343032.324325235) * float(1000) / float(1000), 3)

1324343032.324

1
尽管此代码段可以解决问题,但提供说明确实有助于提高您的帖子质量。请记住,您将来会为读者回答这个问题,而这些人可能不知道您提出代码建议的原因。
— DimaSan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.