简体   繁体   English

在 python 中向下舍入到小数点后两位

[英]round down to 2 decimal in python

I need to round down and it should be two decimal places.我需要四舍五入,它应该是小数点后两位。
Tried the following,尝试了以下,

a = 28.266
print round(a, 2)

28.27 28.27

But the expected value is 28.26 only.但期望值仅为 28.26。

Seems like you need the floor :好像你需要floor

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

# 28.26

It seems you want truncation, not rounding.看来您想要截断,而不是四舍五入。

A simple way would be to combine floor division // and regular division / :一个简单的方法是结合楼层划分//和常规划分/

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

Instead of the regular division you could also multiply (as noted in the comments by cmc ):除了常规除法之外,您还可以乘法(如cmc的评论中所述):

>>> a // 0.01 * 0.01
28.26

Similarly you could create a function to round down to other more/less decimals.同样,您可以创建一个函数来四舍五入到其他更多/更少的小数。 But because floats are inexact numbers, this can lead to inaccuracies.但是因为浮点数是不精确的数字,所以这可能会导致不准确。

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

print(round_down(28.266, 2))
# 28.26

But as said it's not exactly exact:但正如所说,它并不完全准确:

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

There are other (more precise) approaches though:还有其他(更精确的)方法:

A solution using the fraction module使用fraction模块的解决方案

A fraction can represent a decimal number much more exact than a float . fraction可以比float更精确地表示十进制数。 Then one can use the "multiply, then floor, then divide" approach mentioned by Psidom but with significantly higher precision:然后可以使用 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

And using the test I did with the floats:并使用我对浮点数进行的测试:

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

However creating a Fraction will not magically fix an inexact float , so typically one should create the Fraction from a string or a "numerator-denominator pair" instead of from float.然而,创建Fraction不会神奇地修复不精确的float ,因此通常应该从字符串或“分子-分母对”而不是从 float 创建Fraction

A solution using the decimal module使用decimal模块的解决方案

You could also use the decimal module, which offers a variety of rounding modes, including rounding down.您还可以使用decimal模块,它提供多种舍入模式,包括向下舍入。

For this demonstration I'm using a context manager to avoid changing the decimal rounding mode globally:对于这个演示,我使用上下文管理器来避免全局更改小数舍入模式:

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))  # 28.26

Which gives more sensible results for the rounding:这为四舍五入提供了更合理的结果:

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

As with Fraction a Decimal should be created from a string to avoid the intermediate inexact float.Fraction一样,应从字符串创建Decimal以避免中间不精确的浮点数。 But different from Fraction the Decimal have limited precision, so for values with lots of significant figures it will also become inexact.但是,从不同的FractionDecimal具有精度有限,所以有很多的显著数字也将成为不准确的值。

However "rounding down" is just one of the available options.然而,“四舍五入”只是可用选项之一。 The list of available rounding modes is extensive: 可用的舍入模式列表非常广泛:

Rounding modes舍入模式

decimal.ROUND_CEILING Round towards Infinity. decimal.ROUND_CEILING向无穷大decimal.ROUND_CEILING

decimal.ROUND_DOWN Round towards zero. decimal.ROUND_DOWN向零decimal.ROUND_DOWN

decimal.ROUND_FLOOR Round towards -Infinity. decimal.ROUND_FLOOR向 -Infinity decimal.ROUND_FLOOR

decimal.ROUND_HALF_DOWN Round to nearest with ties going towards zero. decimal.ROUND_HALF_DOWN到最接近的关系,并趋向于零。

decimal.ROUND_HALF_EVEN Round to nearest with ties going to nearest even integer. decimal.ROUND_HALF_EVEN入到最接近的整数,关系到最近的偶数。

decimal.ROUND_HALF_UP Round to nearest with ties going away from zero. decimal.ROUND_HALF_UP到最接近的关系,从零开始。

decimal.ROUND_UP Round away from zero. decimal.ROUND_UP入。

decimal.ROUND_05UP Round away from zero if last digit after rounding towards zero would have been 0 or 5; decimal.ROUND_05UP如果向零四舍五入后的最后一位数字为 0 或 5,则从零四舍五入; otherwise round towards zero.否则向零舍入。

With Python 3.9, you can use quantize()使用 Python 3.9,您可以使用 quantize()

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

I tested the above answer and it worked.我测试了上面的答案并且它起作用了。 But I find this 1 liner is quite simple.但我发现这个 1 班轮很简单。 So I also write my answer here.所以我也在这里写下我的答案。

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

simply try this:试试这个:

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

Output:输出:

28.26

here's a simple function that isn't affected by float precision errors这是一个不受浮点精度误差影响的简单函数

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

Tests:测试:

>>> truncate_float(28.266, 3)
28.266
>>> truncate_float(28.266, 2)
28.26
>>> truncate_float(28.266, 1)
28.2

There's an even simpler way of doing this generically, by subtracting a small quantity before rounding, like so:一般情况下,还有一种更简单的方法,即在四舍五入之前减去少量,如下所示:

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

This is based on the intuition that one way of rounding a float to the nearest integer is by adding 0.5, then truncating.这是基于直觉,将浮点数四舍五入到最接近的整数的一种方法是加上 0.5,然后截断。 The above solution does the opposite by subtracting a half of the minimal 'tick' that the desired precision allows, then rounding.上述解决方案通过减去所需精度允许的最小“刻度”的一半,然后四舍五入来实现相反的效果。

Simple function which you can use in your codes.您可以在代码中使用的简单功能。 This function you can also use for integer floor numbers.此函数也可用于整数楼层数。

import math
def floorDecimal(number, decimal):
    return math.floor(number * pow(10, decimal))/pow(10, decimal)

Example of using:使用示例:

number = 256.789
newNumber = floorDecimal(number, 2) # newNumber is 256.78
newNumber = floorDecimal(number, -2) # newNumber is 200

Here is the function I use with f for the float and d for the number of decimals这是我使用f表示浮点数和d表示小数位数的函数

from math import floor

def floor_decimal(f, d):
    n = 10 ** d
    return floor(f * n) / n

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM