Python 3.x向上取整

2024-04-19 15:13:17 发布

您现在位置:Python中文网/ 问答频道 /正文

我知道在python中关于舍入的问题已经被问过很多次了,但是答案对我没有帮助。我正在寻找一个方法,它将浮点数四舍五入并返回一个浮点数。该方法还应接受一个参数,该参数定义要舍入到的小数位数。我写了一个实现这种舍入的方法。不过,我觉得它看起来一点也不优雅。在

def round_half_up(number, dec_places):
    s = str(number)

    d = decimal.Decimal(s).quantize(
        decimal.Decimal(10) ** -dec_places,
        rounding=decimal.ROUND_HALF_UP)

    return float(d)

我不喜欢这样,我必须将float转换为字符串(以避免浮点不准确),然后使用decimal模块。 你有更好的解决办法吗?在

编辑:正如下面的答案所指出的,我的问题的解决方案并不是那么明显,因为正确的舍入首先需要正确的数字表示,而float则不是这样。所以我希望下面的代码

^{pr2}$

(这与上面的代码不同,只是浮点数直接转换成十进制数,而不是先转换成字符串)在这样使用时返回2.18:round_half_up(2.175, 2),但不是因为{}将返回{},这是计算机表示浮点数的方式。 令人惊讶的是,第一个代码返回2.18,因为浮点数首先被转换为字符串。str()函数似乎对最初要四舍五入的数字执行隐式舍入。所以有两个回合。尽管这是我所期待的结果,但它在技术上是错误的。在


Tags: 方法字符串答案代码number参数floatdec
3条回答

舍入是非常困难的,因为必须非常小心地处理浮点计算。如果您正在寻找一个优雅的解决方案(简短、易于理解),那么您所拥有的就像一个好的起点。为了正确起见,您应该用从数字本身创建十进制来替换decimal.Decimal(str(number)),这将为您提供精确表示的十进制版本:

d = Decimal(number).quantize(...)...

Decimal(str(number))有效地将取整两次,因为将float格式化为字符串表示将执行自身的舍入。这是因为str(float value)不会尝试打印浮点的完整十进制表示形式,它只会打印足够的数字,以确保在将这些精确的数字传递给float构造函数时获得相同的浮点值。在

如果您想保留正确的舍入,但是避免依赖于庞大而复杂的decimal模块,那么您当然可以这样做,但是您仍然需要一些方法来实现正确舍入所需的精确算法。例如,可以使用fractions

^{pr2}$

请注意,上面代码中唯一棘手的部分是浮点到分数的精确转换,这可以卸载到^{}float方法,这是小数和分数在内部执行的操作。因此,如果您真的想删除对fractions的依赖,可以将分数算术减少为纯整数运算;您可以保持相同的行数,但要牺牲一些易读性:

^{3}$

请注意,测试这些函数会使创建浮点数时执行的近似值成为焦点。例如,print(round_half_up(2.175, 2))打印2.17,因为十进制数2.175不能精确地用二进制表示,所以它被一个恰好比2.175小的近似值所代替。函数接收到该值,发现它小于2.175十进制数对应的实际分数,并决定将其向下舍入。这并不是实现中的一个怪癖;这种行为源于浮点数的属性,而且在Python 32round内置中也存在。在

I don't like it, that I have to convert float to a string (to avoid floating point inaccuracy) and then work with the decimal module. Do you have any better solutions?

是的;如果您需要精确地表示2.675之类的数字,并将它们舍入到2.68而不是2.67时,请使用Decimal来表示整个程序中的数字。在

别无选择。屏幕上显示为2.675的浮点数不是实数2.675;事实上,它非常小地小于2.675,这就是为什么它被四舍五入到2.67:

>>> 2.675 - 2
0.6749999999999998

它只以字符串形式显示为'2.675',因为这恰好是float(s) == 2.6749999999999998最短的字符串。请注意,这个较长的表示(包含大量的9)也不精确。在

不管您编写的舍入函数如何,my_round(2.675, 2)不可能向上取整为2.68,也不可能让{}向下取整到{};因为输入实际上是同一个浮点数。在

因此,如果你的数字2.675曾经被转换成一个浮点数,然后又变回来,你已经失去了它应该向上取整还是向下取整的信息。解决办法是首先不要让它浮起来。在

在尝试了很长时间来生成一个优雅的单行函数之后,我最终得到了一个与字典大小相当的东西。在

最简单的办法就是

def round_half_up(inp,dec_places):
    return round(inp+0.0000001,dec_places)

我承认这并不是每种情况下都准确,但是如果你只是想要一个简单快速的解决方法,那么它应该是有效的。在

相关问题 更多 >