简体   繁体   English

仅在重复python时才舍入到小数点后两位

[英]Round to two decimal places only if repeating python

I was wondering if anybody knew of a quick way in python to check and see if a fraction gives a repeating decimal. 我想知道是否有人知道用python快速检查并查看分数是否给出重复的小数的方法。

I have a small function that takes in two numbers and divides them. 我有一个小函数,接受两个数字并将它们相除。 If the quotient is a repeating decimal I would like to round to 2 decimal places and if the quotient is not repeating I would like to round to just one 如果商是重复的小数,我想四舍五入到小数点后两位;如果商不重复,我想四舍五入到小数点后一位

Example: 例:

800/600 = 1.33333333333333 which would equal 1.33 800/600 = 1.33333333333333,等于1.33

900/600 = 1.5 would stay as 1.5 900/600 = 1.5将保持为1.5

I know that I need to use the two statements for the two types of rounding 我知道我需要对两种类型的舍入使用这两个语句

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

but I am having trouble with the if statement to direct to one or the other. 但是我在使用if语句定向到另一个时遇到麻烦。

Can anybody help with some insight? 任何人都可以提供一些帮助吗?

Use the fractions module, which implements exact rational arithmetic: 使用fractions模块,该模块实现精确的有理算法:

import fractions

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

You can then inspect the denominator of the result: 然后,您可以检查结果的denominator

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

Try this: Just use brute force. 试试这个:只需使用蛮力。 Since you want only 2 decimal places. 由于您只需要2个小数位。 Just divide and then test it when it is rounded to 0 and 1 decimal place and see where it stops being unique. 只需进行除法,然后将其舍入到小数点后0位和1位,然后进行测试,看看它在哪里不再唯一。 If it is not unique at this point, then round to 2 decimal places. 如果此时它不是唯一的,则四舍五入到小数点后两位。

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

Output: 输出:

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

Just a workaround using regex :) 只是使用正则表达式的解决方法:)

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

Output: 输出:

1.33

And for 900/600 而对于900/600

1.5

repeating decimal 重复小数

There are only 10 fractions that can be written as some repeated digit - .(0) , .(1) , ... .(9) . 只有10个小数部分可以写为重复的数字- .(0).(1) ,...。 .(9) Thus, if you only care about repeating pattern starting right after decimal point, you only need to check against those cases. 因此,如果您只关心从小数点后立即开始重复模式,则只需要检查这些情况即可。

All those numbers (and only them) give an integer if multiplied by 9. 如果将所有这些数字(只有它们)乘以9,则将得到一个整数。

Thus, if (9 * numenator) % denominator == 0 , you'll print 2 digits. 因此,如果(9 * numenator) % denominator == 0(9 * numenator) % denominator == 0输出2位数字。

You'll probably want to exclude .(0) pattern though. 您可能会想要排除.(0)模式。 To do that, test if your fraction is in fact an integer - numenator % denominator == 0 . 为此,请测试您的分数是否实际上是整数- numenator % denominator == 0

Also check out fractions module in case you have some wheels to reinvent. 还要检查分数模块,以防您需要重新发明一些轮子。

Of course, if you only have your number as a float , there is some ambiguity about what numenator and denominator are, because float s don't actually store rational numbers like 1/3 . 当然,如果您只将数字作为float ,则对分子和分母是些歧义,因为float实际上并未存储1/3类的有理数。 You can experiment with fractions 's .limit_denominator() to choose something that works for your case. 您可以尝试使用fractions.limit_denominator()选择适合您情况的内容。

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

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