在python中向下舍入到2位小数

时间:2016-12-29 16:42:55

标签: python rounding

我需要向下舍入,它应该是小数点后两位 尝试以下,

a = 28.266
print round(a, 2)
  

28.27

但预期值仅为28.26。

6 个答案:

答案 0 :(得分:8)

好像你需要floor

import math
math.floor(a * 100)/100.0

# 28.26

答案 1 :(得分:4)

似乎你想要截断,而不是四舍五入。

一种简单的方法是将地板划分//和常规划分/结合起来:

>>> a = 28.266
>>> a // 0.01 / 100
28.26

除了常规除法之外,您还可以乘以(如cmc中的评论中所述):

>>> a // 0.01 * 0.01
28.26

类似地,您可以创建一个函数来向下舍入到其他更多/更少的小数,但由于浮点数是不精确的数字,这可能会导致不准确。

def round_down(value, decimals):
    factor = 1 / (10 ** decimals)
    return (value // factor) * factor

print(round_down(28.266, 2))
# 28.26

但正如所说,它并不完全准确:

for i in range(0, 8):
    print(i, round_down(12.33333, i))
0 12.0
1 12.3
2 12.33
3 12.333
4 12.333300000000001 # weird, but almost correct
5 12.33332           # wrong
6 12.33333
7 12.33333

还有其他(更精确)的方法:

使用fraction模块

的解决方案

fraction s可以表示比float更精确的十进制数。然后可以使用乘法,然后是地板,然后除以Psidom提到的方法,但具有更高的精度:

或作为功能:

import fractions
import math

a = 28.266

def round_down(value, decimals):
    factor = 10 ** decimals
    f = fractions.Fraction(value)
    return fractions.Fraction(math.floor(f * factor),  factor)

print(round_down(28.266, 2))
# 1413/50  <- that's 28.26

使用我用浮子做的测试:

for i in range(0, 8):
    print(i, round_down(12.33333, i))
0 12
1 123/10
2 1233/100
3 12333/1000
4 123333/10000
5 1233333/100000
6 1233333/100000
7 1233333/100000

但是,创建Fraction不会神奇地修复不精确的float,因此通常应该从字符串或分子 - 分母对而不是浮点数创建Fraction

使用decimal模块

的解决方案

您还可以使用decimal模块,该模块提供各种舍入模式,包括向下舍入。

对于本演示,我使用上下文管理器来避免永久更改小数舍入模式:

import decimal

def round_down(value, decimals):
    with decimal.localcontext() as ctx:
        d = decimal.Decimal(value)
        ctx.rounding = decimal.ROUND_DOWN
        return round(d, decimals)

print(round_down(28.266, 2))

这为舍入提供了更明智的结果:

for i in range(0, 8):
    print(i, round_down(12.33333, i))
0 12
1 12.3
2 12.33
3 12.333
4 12.3333
5 12.33333
6 12.333330
7 12.3333300

Fraction一样,应该从字符串创建Decimal以避免中间不精确的浮点数。但与Fraction不同,Decimal的精度有限,因此对于具有大量有效数字的值,它也会变得不精确。

然而,四舍五入只是可用选项之一。 available rounding modes的列表非常广泛:

  

舍入模式

     

decimal.ROUND_CEILING向无限转。

     

decimal.ROUND_DOWN向零回合。

     

decimal.ROUND_FLOOR向无穷大方向前进。

     

decimal.ROUND_HALF_DOWN四舍五入到最接近的关系为零。

     

decimal.ROUND_HALF_EVEN舍入到最接近的关系到最近的偶数。

     

decimal.ROUND_HALF_UP四舍五入到距离零最近的关系。

     

decimal.ROUND_UP离开零点。

     

decimal.ROUND_05UP如果舍入为零后的最后一位数字为0或5,则从零开始;否则往零。

答案 2 :(得分:3)

试试这个:

import math
a = 28.266
print((math.floor(a * 100)) / 100.0)

输出:

28.26

答案 3 :(得分:2)

这是一个不受浮点精度错误影响的简单函数

import psycopg2, sqlite3, sys
import time
import asyncio


sqdb="D://Python//SqliteToPostgreFull//testmydb6.db"
sqlike="table"
pgdb="testmydb9"
pguser="postgres"
pgpswd="1234"
pghost="127.0.0.1"
pgport="5432"


consq=sqlite3.connect(sqdb)
cursq=consq.cursor()

tabnames=[]
print() 
cursq.execute('''SELECT name FROM sqlite_master WHERE type="table" AND name LIKE "'''+sqlike+'''%";''')
tabgrab = cursq.fetchall()
for item in tabgrab:
    tabnames.append(item[0])
print(tabgrab)

async def copyTable(table):
    cursq.execute("SELECT sql FROM sqlite_master WHERE type='table' AND name = ?;", (table,))
    create = cursq.fetchone()[0]
    cursq.execute("SELECT * FROM %s;" %table)
    rows=cursq.fetchall()
    colcount=len(rows[0])
    pholder='%s,'*colcount
    newholder=pholder[:-1]

    try:

        conpg = psycopg2.connect(database=pgdb, user=pguser, password=pgpswd,
                               host=pghost, port=pgport)
        curpg = conpg.cursor()
        curpg.execute("DROP TABLE IF EXISTS %s;" %table)
        create = create.replace("AUTOINCREMENT", "")
        curpg.execute(create)
        curpg.executemany("INSERT INTO %s VALUES (%s);" % (table, newholder),rows)
        conpg.commit()

        if conpg:
            conpg.close()

    except psycopg2.DatabaseError as e:
        print ('Error %s' % e) 
        sys.exit(1)

    finally:
        print("Complete")

async def main():
    for table in tabnames:
        a = loop.create_task(copyTable(table,))
    await asyncio.wait([a])

if __name__ == "__main__":
    start_time = time.time()
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
    loop.close()      
    duration = time.time() - start_time
    print(f"Duration {duration} seconds")

测试:

def truncate_float(n, places):
    return int(n * (10 ** places)) / 10 ** places

答案 4 :(得分:1)

在Python 3.9中,您可以使用Quantize()

from decimal import *    
>>> Decimal('7.325').quantize(Decimal('.01'), rounding=ROUND_DOWN)
Decimal('7.32')

我测试了以上答案,并成功了。但是我发现这1班轮很简单。所以我也在这里写下我的答案。

来源:https://docs.python.org/3/library/decimal.html

答案 5 :(得分:0)

一般来说,还有一种更简单的方法,就是在四舍五入之前减去少量,就像这样:

a = 28.269
digits = 2
print(round(a - 0.5/10**digits, digits))

这是基于这样的直觉:将浮点数四舍五入到最接近的整数的一种方法是先加上0.5,然后截断。上述解决方案则相反,其方法是减去所需精度允许的最小“刻度”的一半,然后四舍五入。