在Python中将浮点数向下舍入,保留一个非零小数位。

13

我有一个Python列表,只有浮点数:

list_num = [0.41, 0.093, 0.002, 1.59, 0.0079, 0.080, 0.375]

我需要将这个列表四舍五入得到:

list_num_rounded = [0.4, 0.09, 0.002, 1.5, 0.007, 0.08, 0.3]

问题: 将1.59四舍五入为1.5很容易。但是,我的问题在于小于1的浮点数。

问题: 基本上,我需要将所有浮点数向下取整,以便:如果浮点数< 1,则四舍五入后的版本仅包含一个非零数字。有没有办法在Python 2.7中实现这一点?

尝试: 这是我尝试过的:

list_num_rounded = []
for elem in list_num:
    if elem > 0.01 and elem < 0.1:
        list_num_rounded.append(round(elem,2))
    if elem > 0.001 and elem < 0.01:
        list_num_rounded.append(round(elem,3))
    elif elem > 0.1:
        list_num_rounded.append(round(elem,1))

然而,这样会得到:

[0.4, 0.09, 0.002, 1.6, 0.008, 0.08, 0.4]

它将1.59、0.79和0.375四舍五入,但我需要一种只舍不入的方法。有什么办法吗?

列表中不包含负浮点数,只有正浮点数。

4个回答

8

您可以使用对数来计算前导零的数量,然后需要一种向下取整的方法。一种方法是使用floor函数,如下所示:

import math

list_num = [0.41, 0.093, 0.002, 1.59, 0.0079, 0.080, 0.375, 0, 10.1, -0.061]


def myround(n):
    if n == 0:
        return 0
    sgn = -1 if n < 0 else 1
    scale = int(-math.floor(math.log10(abs(n))))
    if scale <= 0:
        scale = 1
    factor = 10**scale
    return sgn*math.floor(abs(n)*factor)/factor


print [myround(x) for x in list_num]

输出:

[0.4, 0.09, 0.002, 1.5, 0.007, 0.08, 0.3]

我不确定您如何处理负数和大于1的数字,此方法将负数四舍五入为1位小数并将大于1的数字四舍五入为1。

我更新了原始帖子。列表中不会有负浮点数。关于大于1的数字,抱歉我可能没有理解。你的例子中已经有一个大于1的数字——> 1.59。你的解决方案对此有效吗? - edesz
我似乎无法解决大于1的数字问题。我有什么遗漏吗? - edesz
1
是的,我在示例数据中看到了1.59。但是,例如,1059.56会四舍五入到哪里?我假设它会向下舍入到1个小数位(因此为1059.5)。 - reupen
啊,我明白了。感谢您的澄清。我可以添加一个if语句来单独处理这种情况。我将接受这个答案,因为您的函数似乎对原帖中列出的所有其他情况都有效。谢谢! - edesz
没问题,很高兴能帮忙 :) - reupen

3

鉴于所有的浮点数都是正数,您可以将它们转换为字符串,并像这样使用切片。

def round(num):
    working = str(num-int(num))
    for i, e in enumerate(working[2:]):
        if e != '0':
            return int(num) + float(working[:i+3])

list_num = [0.41, 0.093, 0.002, 1.59, 0.0079, 0.080, 0.375]
new_list = [round(x) for x in list_num]
print new_list

打印
[0.4, 0.09, 0.002, 1.5, 0.007, 0.08, 0.3]

如果列表中可能有浮点数,在小数点后没有非零值,您需要添加一个简单的检查来处理它。


3
def round_float(num):
    if not num:
        return num
    current_num = abs(num) * 10
    round_value = 1

    while not (current_num//1):
        current_num *= 10
        round_value +=1

    return round(num, round_value)

请注释您的代码并分享您所做的工作以及为什么您的答案是有效的。 - Unbranded Manchester
@UnbrandedManchester 你挺苛刻的,我认为这是最优雅的解决方案,并且代码本身说明了一切。 - mikakun

2

将浮点数格式化为科学计数法可能会有帮助;然后将其转换回浮点类型应该可以实现您想要的效果。尝试类似以下的内容:

eval("%.0e" % (.03))
eval("%.0e" % (.034))
eval("%.0e" % (.0034))

谢谢。但我不确定我理解了。我尝试了 print eval("%.0e" % (.375)),结果得到了 0.4。你有例子吗? - edesz
2
对于大于1的数字,这种方法并不完全适用。举个例子:如果你这样做[eval("%.0e"%(element)) for element in list_num],1.59会变成2.0。 - Leo
你是对的,它会将数字四舍五入到一位小数,但不会向下取整。如果你想尝试相同的方法,可以尝试类似这样的代码:x="%.1e" % (.375); eval( x[:2]+"0"+x[3:]) - Thomas Baruchel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接