仅在Python中出现重复时将结果四舍五入到两位小数

3

我想知道在Python中是否有一种快速的方法来检查分数是否为循环小数。

我有一个小函数,它接受两个数字并将它们相除。如果商是循环小数,我想要将其四舍五入到2位小数,如果商不是循环小数,则只需将其四舍五入到1位小数。

例如:

800/600 = 1.33333333333333,这将等于1.33

900/600 = 1.5 将保持为1.5

我知道我需要使用两种舍入语句来处理这两种类型的舍入。

output = "{:.2f}".format(float(num))
output = "{:,}".format(float(num))

但我在if语句中遇到了麻烦,无法将其指向其中之一。

有人能够提供一些见解帮忙吗?


1
所有的分数都可以用循环小数来表示。就像在学校里做除法一样,检查是否有立即重复的模式。 - Jens Munk
1
你想打印1/1还是5/4? - joel goldstick
啊抱歉,这可能是一个愚蠢的问题。对于1/1,我想显示1,对于5/4,我想显示1.25。我的目标是不显示任何尾随的0。 - markdozer
1
你想要10/99的结果,它是0.101010...吗? - user2357112
我想看到 10/99 = 0.10。 - markdozer
4个回答

2
使用实现精确有理数算术的fractions模块:fractions
import fractions

# fractions.Fraction instances are automatically put in lowest terms.
ratio = fractions.Fraction(numerator, denominator)

您可以检查结果的分母

def is_repeating(fraction):
    denom = fraction.denominator
    while not (denom % 2):
        denom //= 2
    while not (denom % 5):
        denom //= 5
    return denom != 1

1
尝试这样做:只需使用暴力破解。由于您只想要2位小数,因此只需进行除法运算,然后在将其舍入为0和1个小数位时进行测试,并查看何时停止唯一。如果此时不唯一,则舍入为2个小数位。
def f(x):
    if x == round(x,0):
        return '{:.0f}'.format(x)
    elif x == round(x,1):
        return '{:.1f}'.format(x)
    else:
        return round(x,2)

y = [1, 2, 3, 3/2, 1/9, 8/9, 1/11, 12/11, 10/11, 14/13, 1/3]
for item in y:
    print(f(item))

输出:

1
2
3
1.5
0.11
0.89
0.09
1.09
0.91
1.08
0.33
>>> 

1
只是使用正则表达式的解决方法 :)
import re

result = str(800/600)
# result = str(900/600)

repeating_pair = re.escape(result.split('.')[1][:2])
check_within = result.split('.')[1][2:]

if re.match(repeating_pair, check_within):
    print("{:.2f}".format(float(result)))
else:
    print("{:.1f}".format(float(result)))

输出:

1.33

对于900/600


1.5

-1

循环小数

只有10个分数可以写成某些重复的数字 - .(0), .(1), ... .(9)。因此,如果您只关心小数点后面开始的重复模式,则只需要针对这些情况进行检查。

所有这些数字(仅限它们)如果乘以9会得到一个整数。

因此,如果(9 * 分子) % 分母 == 0,则会打印2位数字。

您可能希望排除.(0)模式。为此,请测试您的分数是否实际上是整数 - 分子 % 分母 == 0

此外,如果您有一些需要重新发明的轮子,请查看fractions模块。

当然,如果您只有一个float作为数字,那么关于分子和分母的一些不确定性是存在的,因为float实际上并不存储像1/3这样的有理数。您可以尝试使用fractions.limit_denominator()来选择适合您情况的内容。


“循环小数”包括像1/7和10/99这样的数字。重复部分不一定是单个数字。 - user2357112
这意味着将900/600打印为1.50,但这在OP的示例中并不是这样。 - Daerdemandt
900/600 是有限小数。 - user2357112
它确实有一个重复的小数 - 0 - 这是问题的区别。然而,任何分数都有一个,但不是任何分数部分都具有仅由此模式组成的小数表示形式。 1.5(0)有它的'5',所以它被截断了。 - Daerdemandt
你完全误解了术语“循环小数”的含义,更重要的是,您对该术语的使用不符合提问者的意图。举个例子,提问者希望得到10/99的0.10,其中重复部分为2位数字。 - user2357112
我正在使用一种解释,根据这种解释,问题中的两个示例都与问题描述中的区别相关,并且在这种解释下,问题是有意义的。当然,这种解释可能是错误的,但我无法推测出意图,我只有文本。对于您的示例,可以使用相同的方法,只需将9替换为99即可。 - Daerdemandt

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