我知道在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)
,但不是因为{
舍入是非常困难的,因为必须非常小心地处理浮点计算。如果您正在寻找一个优雅的解决方案(简短、易于理解),那么您所拥有的就像一个好的起点。为了正确起见,您应该用从数字本身创建十进制来替换
decimal.Decimal(str(number))
,这将为您提供精确表示的十进制版本:Decimal(str(number))
有效地将取整两次,因为将float格式化为字符串表示将执行自身的舍入。这是因为str(float value)
不会尝试打印浮点的完整十进制表示形式,它只会打印足够的数字,以确保在将这些精确的数字传递给float
构造函数时获得相同的浮点值。在如果您想保留正确的舍入,但是避免依赖于庞大而复杂的
^{pr2}$decimal
模块,那么您当然可以这样做,但是您仍然需要一些方法来实现正确舍入所需的精确算法。例如,可以使用fractions:请注意,上面代码中唯一棘手的部分是浮点到分数的精确转换,这可以卸载到^{} float方法,这是小数和分数在内部执行的操作。因此,如果您真的想删除对
^{3}$fractions
的依赖,可以将分数算术减少为纯整数运算;您可以保持相同的行数,但要牺牲一些易读性:请注意,测试这些函数会使创建浮点数时执行的近似值成为焦点。例如,
print(round_half_up(2.175, 2))
打印2.17
,因为十进制数2.175
不能精确地用二进制表示,所以它被一个恰好比2.175小的近似值所代替。函数接收到该值,发现它小于2.175十进制数对应的实际分数,并决定将其向下舍入。这并不是实现中的一个怪癖;这种行为源于浮点数的属性,而且在Python 3和2的round
内置中也存在。在是的;如果您需要精确地表示2.675之类的数字,并将它们舍入到2.68而不是2.67时,请使用
Decimal
来表示整个程序中的数字。在别无选择。屏幕上显示为2.675的浮点数不是实数2.675;事实上,它非常小地小于2.675,这就是为什么它被四舍五入到2.67:
它只以字符串形式显示为
'2.675'
,因为这恰好是float(s) == 2.6749999999999998
最短的字符串。请注意,这个较长的表示(包含大量的9)也不精确。在不管您编写的舍入函数如何,}向下取整到{};因为输入实际上是同一个浮点数。在
my_round(2.675, 2)
不可能向上取整为2.68
,也不可能让{因此,如果你的数字2.675曾经被转换成一个浮点数,然后又变回来,你已经失去了它应该向上取整还是向下取整的信息。解决办法是首先不要让它浮起来。在
在尝试了很长时间来生成一个优雅的单行函数之后,我最终得到了一个与字典大小相当的东西。在
最简单的办法就是
我承认这并不是每种情况下都准确,但是如果你只是想要一个简单快速的解决方法,那么它应该是有效的。在
相关问题 更多 >
编程相关推荐