将长数字格式化为字符串

发布于 2024-07-13 21:34:05 字数 184 浏览 5 评论 0原文

在Python中,有什么简单的方法可以将整数格式化为字符串,用K表示千位,用M表示百万位,并且在逗号后只留下几个数字?

我想将 7436313 显示为 7.44M,将 2345 显示为 2,34K。

是否有一些 % 字符串格式化运算符可用? 或者只能通过在循环中实际除以 1000 并逐步构造结果字符串来完成?

What is an easy way in Python to format integers into strings representing thousands with K, and millions with M, and leaving just couple digits after comma?

I'd like to show 7436313 as 7.44M, and 2345 as 2,34K.

Is there some % string formatting operator available for that? Or that could be done only by actually dividing by 1000 in a loop and constructing result string step by step?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

滥情哥ㄟ 2024-07-20 21:34:05

这个版本不会受到之前答案中 999,999 为您提供 1000.0K 的错误的影响。 它还只允许 3 个有效数字并消除尾随 0。

def human_format(num):
    num = float('{:.3g}'.format(num))
    magnitude = 0
    while abs(num) >= 1000:
        magnitude += 1
        num /= 1000.0
    return '{}{}'.format('{:f}'.format(num).rstrip('0').rstrip('.'), ['', 'K', 'M', 'B', 'T'][magnitude])

输出看起来像:

>>> human_format(999999)
'1M'
>>> human_format(999499)
'999K'
>>> human_format(9994)
'9.99K'
>>> human_format(9900)
'9.9K'
>>> human_format(6543165413)
'6.54B'

This version does not suffer from the bug in the previous answers where 999,999 gives you 1000.0K. It also only allows 3 significant figures and eliminates trailing 0's.

def human_format(num):
    num = float('{:.3g}'.format(num))
    magnitude = 0
    while abs(num) >= 1000:
        magnitude += 1
        num /= 1000.0
    return '{}{}'.format('{:f}'.format(num).rstrip('0').rstrip('.'), ['', 'K', 'M', 'B', 'T'][magnitude])

The output looks like:

>>> human_format(999999)
'1M'
>>> human_format(999499)
'999K'
>>> human_format(9994)
'9.99K'
>>> human_format(9900)
'9.9K'
>>> human_format(6543165413)
'6.54B'
花开浅夏 2024-07-20 21:34:05

我认为没有内置函数可以做到这一点。 你必须自己动手,例如:

def human_format(num):
    magnitude = 0
    while abs(num) >= 1000:
        magnitude += 1
        num /= 1000.0
    # add more suffixes if you need them
    return '%.2f%s' % (num, ['', 'K', 'M', 'G', 'T', 'P'][magnitude])

print('the answer is %s' % human_format(7436313))  # prints 'the answer is 7.44M'

I don't think there's a built-in function that does that. You'll have to roll your own, e.g.:

def human_format(num):
    magnitude = 0
    while abs(num) >= 1000:
        magnitude += 1
        num /= 1000.0
    # add more suffixes if you need them
    return '%.2f%s' % (num, ['', 'K', 'M', 'G', 'T', 'P'][magnitude])

print('the answer is %s' % human_format(7436313))  # prints 'the answer is 7.44M'
世态炎凉 2024-07-20 21:34:05

更“数学”的解决方案是使用 math.log:

from math import log, floor


def human_format(number):
    units = ['', 'K', 'M', 'G', 'T', 'P']
    k = 1000.0
    magnitude = int(floor(log(number, k)))
    return '%.2f%s' % (number / k**magnitude, units[magnitude])

测试:

>>> human_format(123456)
'123.46K'
>>> human_format(123456789)
'123.46M'
>>> human_format(1234567890)
'1.23G'

A more "math-y" solution is to use math.log:

from math import log, floor


def human_format(number):
    units = ['', 'K', 'M', 'G', 'T', 'P']
    k = 1000.0
    magnitude = int(floor(log(number, k)))
    return '%.2f%s' % (number / k**magnitude, units[magnitude])

Tests:

>>> human_format(123456)
'123.46K'
>>> human_format(123456789)
'123.46M'
>>> human_format(1234567890)
'1.23G'
作业与我同在 2024-07-20 21:34:05

精度可变且无 999999 bug:

def human_format(num, round_to=2):
    magnitude = 0
    while abs(num) >= 1000:
        magnitude += 1
        num = round(num / 1000.0, round_to)
    return '{:.{}f}{}'.format(num, round_to, ['', 'K', 'M', 'G', 'T', 'P'][magnitude])

Variable precision and no 999999 bug:

def human_format(num, round_to=2):
    magnitude = 0
    while abs(num) >= 1000:
        magnitude += 1
        num = round(num / 1000.0, round_to)
    return '{:.{}f}{}'.format(num, round_to, ['', 'K', 'M', 'G', 'T', 'P'][magnitude])
优雅的叶子 2024-07-20 21:34:05

我今天需要这个函数,为 Python >= 3.6 的人刷新了接受的答案:

def human_format(num, precision=2, suffixes=['', 'K', 'M', 'G', 'T', 'P']):
    m = sum([abs(num/1000.0**x) >= 1 for x in range(1, len(suffixes))])
    return f'{num/1000.0**m:.{precision}f}{suffixes[m]}'

print('the answer is %s' % human_format(7454538))  # prints 'the answer is 7.45M'

编辑:鉴于注释,您可能需要更改为 round(num/1000.0)

I needed this function today, refreshed the accepted answer a bit for people with Python >= 3.6:

def human_format(num, precision=2, suffixes=['', 'K', 'M', 'G', 'T', 'P']):
    m = sum([abs(num/1000.0**x) >= 1 for x in range(1, len(suffixes))])
    return f'{num/1000.0**m:.{precision}f}{suffixes[m]}'

print('the answer is %s' % human_format(7454538))  # prints 'the answer is 7.45M'

Edit: given the comments, you might want to change to round(num/1000.0)

脱离于你 2024-07-20 21:34:05

Numerize 库很好。

from numerize import numerize
a = numerize.numerize(1000)
print(a)
1k

感谢@tdy 指出这一点,

a = numerize.numerize(999999) 
print(a)  # 1000K 
1000K

Numerize library is good.

from numerize import numerize
a = numerize.numerize(1000)
print(a)
1k

Thanks @tdy for pointing this,

a = numerize.numerize(999999) 
print(a)  # 1000K 
1000K
弱骨蛰伏 2024-07-20 21:34:05

我对其他人展示的一些内容感到有点困惑,所以我编写了下面的代码。 它四舍五入到小数点后第二位,例如。 “235.6 亿”,但您可以通过用更大或更小的数字替换最后一行中的两个“100.0”来更改其舍入到的小数位,例如。 “10.0”四舍五入到小数点后一位,“1000.0”四舍五入到小数点后三位。 此外,使用此代码时,它总是从实际值向下舍入。 如果您愿意,可以更改此设置,将“地板”替换为“天花板”或“圆形”。

#make the dictionary to store what to put after the result (ex. 'Billion'). You can go further with this then I did, or to wherever you wish. 
#import the desired rounding mechanism. You will not need to do this for round. 
from math import floor
magnitudeDict={0:'', 1:'Thousand', 2:'Million', 3:'Billion', 4:'Trillion', 5:'Quadrillion', 6:'Quintillion', 7:'Sextillion', 8:'Septillion', 9:'Octillion', 10:'Nonillion', 11:'Decillion'}
def simplify(num):
    num=floor(num)
    magnitude=0
    while num>=1000.0:
        magnitude+=1
        num=num/1000.0
    return(f'{floor(num*100.0)/100.0} {magnitudeDict[magnitude]}')

最后一行字符串之前的“f”是为了让 python 知道你正在格式化它。 运行 print(simplify(34867123012.13)) 的结果是这样的:

34.86 Billion

如果您有疑问,请告诉我!
谢谢,
安格斯

I was kind of confused by some of the stuff that other people showed, so I made the below code. It rounds to the second decimal point, ex. '23.56 Billion', but you can change what decimal place it rounds to by replacing the two '100.0's in the last line with a larger or smaller number, ex. '10.0' rounds to one decimal point and '1000.0' rounds to three decimal points. Also, using this code, it always rounds down from what it actually is. You can change this if you like, by replacing 'floor' with 'ceil' or 'round'.

#make the dictionary to store what to put after the result (ex. 'Billion'). You can go further with this then I did, or to wherever you wish. 
#import the desired rounding mechanism. You will not need to do this for round. 
from math import floor
magnitudeDict={0:'', 1:'Thousand', 2:'Million', 3:'Billion', 4:'Trillion', 5:'Quadrillion', 6:'Quintillion', 7:'Sextillion', 8:'Septillion', 9:'Octillion', 10:'Nonillion', 11:'Decillion'}
def simplify(num):
    num=floor(num)
    magnitude=0
    while num>=1000.0:
        magnitude+=1
        num=num/1000.0
    return(f'{floor(num*100.0)/100.0} {magnitudeDict[magnitude]}')

The 'f' before the string in the last line is to let python know you are formatting it. The result from running print(simplify(34867123012.13)) is this:

34.86 Billion

Please let me know if you have questions!
Thanks,
Angus

莫相离 2024-07-20 21:34:05

我有同样的需要。 如果有人涉及这个主题,我找到了一个库来这样做: https://github.com/azaitsev/ millify

希望有帮助:)

I had the same need. And if anyone comes on this topic, I found a lib to do so: https://github.com/azaitsev/millify

Hope it helps :)

稳稳的幸福 2024-07-20 21:34:05

根据这里的评论,我为此编写了改进的代码。 它有点长,但给出了更多情况的解决方案,包括小数字(m,u,n,p)。

有帮助

# print number in a readable format.
# default is up to 3 decimal digits and can be changed
# works on numbers in the range of 1e-15 to 1e 1e15 include negatives numbers
# can force the number to a specific magnitude unit
def human_format(num:float, force=None, ndigits=3):
    perfixes = ('p', 'n', 'u', 'm', '', 'K', 'M', 'G', 'T')
    one_index = perfixes.index('')
    if force:
        if force in perfixes:
            index = perfixes.index(force)
            magnitude = 3*(index - one_index)
            num = num/(10**magnitude)
        else:
            raise ValueError('force value not supported.')
    else:
        div_sum = 0
        if(abs(num) >= 1000):
            while abs(num) >= 1000:
                div_sum += 1
                num /= 1000
        else:
            while abs(num) <= 1:
                div_sum -= 1
                num *= 1000
        temp = round(num, ndigits) if ndigits else num
        if temp < 1000:
            num = temp 
        else:
            num = 1
            div_sum += 1
        index = one_index + div_sum
    return str(num).rstrip('0').rstrip('.') + perfixes[index]

希望这对从这里进行测试的人和其他人

# some tests
print(human_format(999)              ,' = '         , '999') 
print(human_format(999.999)          ,' = '         , '999.999') 
print(human_format(999.9999)         ,' = '         , '1K')  
print(human_format(999999)           ,' = '         , '999.999K')   
print(human_format(999499)           ,' = '         , '999.499K')   
print(human_format(9994)             ,' = '         , '9.994K')   
print(human_format(9900)             ,' = '         , '9.9K')   
print(human_format(6543165413)       ,' = '         , '6.543G')  
print(human_format(46780.9)          ,' = '         , '46.781K')  
print(human_format(0.001)            ,' = '         , '1m')   
print(human_format(0.000000999999)   ,' = '         , '999.999n')  
print(human_format(1.00394200)       ,' = '         , '1.004')   
print(human_format(0.0999)           ,' = '         , '99.9m')  
print(human_format(0.00000000999999) ,' = '         , '10n') 
print(human_format(0.0000000099995)  ,' = '         , '9.999n')  
print(human_format(0.000000009999)   ,' = '         , '9.999n') 
print(human_format(999999            ,ndigits=2)    ,' = '           , '1M')   
print(human_format(9994              ,force='')     ,' = '           , '9994K')   
print(human_format(6543165413        ,ndigits=5)    ,' = '           , '6.54317G')  
print(human_format(6543165413        ,ndigits=None) ,' = '           , '6.543165413G')  
print(human_format(7436313           ,ndigits=2)    ,' = '           , '7.44M')   
print(human_format(2344              ,ndigits=2)    ,' = '           , '2.34K')
print(human_format(34867123012.13    ,ndigits=2)    ,' = '           , '34.87G')   

Based on the comments here, I made an improved code for that. It is a little bit longer but gives solutions for more cases including small numbers (m,u,n,p).

Hope it will be helpful for someone

# print number in a readable format.
# default is up to 3 decimal digits and can be changed
# works on numbers in the range of 1e-15 to 1e 1e15 include negatives numbers
# can force the number to a specific magnitude unit
def human_format(num:float, force=None, ndigits=3):
    perfixes = ('p', 'n', 'u', 'm', '', 'K', 'M', 'G', 'T')
    one_index = perfixes.index('')
    if force:
        if force in perfixes:
            index = perfixes.index(force)
            magnitude = 3*(index - one_index)
            num = num/(10**magnitude)
        else:
            raise ValueError('force value not supported.')
    else:
        div_sum = 0
        if(abs(num) >= 1000):
            while abs(num) >= 1000:
                div_sum += 1
                num /= 1000
        else:
            while abs(num) <= 1:
                div_sum -= 1
                num *= 1000
        temp = round(num, ndigits) if ndigits else num
        if temp < 1000:
            num = temp 
        else:
            num = 1
            div_sum += 1
        index = one_index + div_sum
    return str(num).rstrip('0').rstrip('.') + perfixes[index]

tests from here and some more

# some tests
print(human_format(999)              ,' = '         , '999') 
print(human_format(999.999)          ,' = '         , '999.999') 
print(human_format(999.9999)         ,' = '         , '1K')  
print(human_format(999999)           ,' = '         , '999.999K')   
print(human_format(999499)           ,' = '         , '999.499K')   
print(human_format(9994)             ,' = '         , '9.994K')   
print(human_format(9900)             ,' = '         , '9.9K')   
print(human_format(6543165413)       ,' = '         , '6.543G')  
print(human_format(46780.9)          ,' = '         , '46.781K')  
print(human_format(0.001)            ,' = '         , '1m')   
print(human_format(0.000000999999)   ,' = '         , '999.999n')  
print(human_format(1.00394200)       ,' = '         , '1.004')   
print(human_format(0.0999)           ,' = '         , '99.9m')  
print(human_format(0.00000000999999) ,' = '         , '10n') 
print(human_format(0.0000000099995)  ,' = '         , '9.999n')  
print(human_format(0.000000009999)   ,' = '         , '9.999n') 
print(human_format(999999            ,ndigits=2)    ,' = '           , '1M')   
print(human_format(9994              ,force='')     ,' = '           , '9994K')   
print(human_format(6543165413        ,ndigits=5)    ,' = '           , '6.54317G')  
print(human_format(6543165413        ,ndigits=None) ,' = '           , '6.543165413G')  
print(human_format(7436313           ,ndigits=2)    ,' = '           , '7.44M')   
print(human_format(2344              ,ndigits=2)    ,' = '           , '2.34K')
print(human_format(34867123012.13    ,ndigits=2)    ,' = '           , '34.87G')   
李白 2024-07-20 21:34:05

我知道这是一个老问题,但我想补充一句:

>>> human_format = lambda num: [f'{num/10**(3*i):.0f}{k}' for i, k in enumerate(' kMGTPEZY') if num >= 10**(3*i) * 0.9995][-1]
>>> human_format(10_000)
'10k'
>>> human_format(12_345_678)
'12M'
>>> human_format(999_999)
'1M'

I know this is an old question but I'd like to add this one-liner:

>>> human_format = lambda num: [f'{num/10**(3*i):.0f}{k}' for i, k in enumerate(' kMGTPEZY') if num >= 10**(3*i) * 0.9995][-1]
>>> human_format(10_000)
'10k'
>>> human_format(12_345_678)
'12M'
>>> human_format(999_999)
'1M'
木緿 2024-07-20 21:34:05

没有字符串格式化运算符,根据文档。 我从来没有听说过这样的事情,所以你可能必须按照你的建议自己动手。

No String Formatting Operator, according to the docs. I've never heard of such a thing, so you may have to roll your own, as you suggest.

梦行七里 2024-07-20 21:34:05

我认为没有格式运算符,但您可以简单地除以 1000,直到结果介于 1 和 999 之间,然后使用逗号后的 2 位数字的格式字符串。 在大多数情况下,单位是单个字符(或者可能是一个小字符串),您可以将其存储在字符串或数组中,并在每次除法后对其进行迭代。

I don't think there are format operators for that, but you can simply divide by 1000 until the result is between 1 and 999 and then use a format string for 2 digits after comma. Unit is a single character (or perhaps a small string) in most cases, which you can store in a string or array and iterate through it after each divide.

绝情姑娘 2024-07-20 21:34:05
def human_format(value):
   num = value
   magnitude = 0
   while abs(num) >= 1000:
      magnitude += 1
      num /= 1000.0
   result = round(value / (1000**magnitude),3)
   return '{}{}'.format(result, ['', 'K', 'M', 'B', 'T'][magnitude])
def human_format(value):
   num = value
   magnitude = 0
   while abs(num) >= 1000:
      magnitude += 1
      num /= 1000.0
   result = round(value / (1000**magnitude),3)
   return '{}{}'.format(result, ['', 'K', 'M', 'B', 'T'][magnitude])
云淡月浅 2024-07-20 21:34:05

刚刚为此创建了一个函数:

基本

def format_numbers(num: int):
    digits = f"{num:,}"
    comma = digits.count(",")
    seperates = {
      "1": "K",
      "2": "M",
      "3": "B",
      "4": "T",
      "5": "Q",
      "6": "S",
      "7": "O",
      "8": "N",
    }
    seperate = seperates.get(str(comma), "N/A")
    if seperate == "N/A":
        return digits
    return f'{digits[:digits.find(",")]}{seperate}'

高级:

def format_numbers(num: int, max_fraction_digits: int = 1):
    digits = f"{num:,}"
    comma = digits.count(",")
    seperates = {
      "1": "K",
      "2": "M",
      "3": "B",
      "4": "T",
      "5": "Q",
      "6": "S",
      "7": "O",
      "8": "N",
    }
    seperate = seperates.get(str(comma), "N/A")
    if seperate == "N/A":
        return digits
    second = digits.split(",")[1]
    if max_fraction_digits and (p:=second[:max_fraction_digits]) != "0":
        return f'{digits[:digits.find(",")]}.{p}{seperate}'
    else:
        return f'{digits[:digits.find(",")]}{seperate}'
      

print(format_numbers(10100000)) # 10.1M
print(format_numbers(10100, 2)) # 10.1K
print(format_numbers(1700000)) # 1.7M
print(format_numbers(1_751_000_000, 2)) # 1.75B

Just made a function for this:

Basic:

def format_numbers(num: int):
    digits = f"{num:,}"
    comma = digits.count(",")
    seperates = {
      "1": "K",
      "2": "M",
      "3": "B",
      "4": "T",
      "5": "Q",
      "6": "S",
      "7": "O",
      "8": "N",
    }
    seperate = seperates.get(str(comma), "N/A")
    if seperate == "N/A":
        return digits
    return f'{digits[:digits.find(",")]}{seperate}'

Advanced:

def format_numbers(num: int, max_fraction_digits: int = 1):
    digits = f"{num:,}"
    comma = digits.count(",")
    seperates = {
      "1": "K",
      "2": "M",
      "3": "B",
      "4": "T",
      "5": "Q",
      "6": "S",
      "7": "O",
      "8": "N",
    }
    seperate = seperates.get(str(comma), "N/A")
    if seperate == "N/A":
        return digits
    second = digits.split(",")[1]
    if max_fraction_digits and (p:=second[:max_fraction_digits]) != "0":
        return f'{digits[:digits.find(",")]}.{p}{seperate}'
    else:
        return f'{digits[:digits.find(",")]}{seperate}'
      

print(format_numbers(10100000)) # 10.1M
print(format_numbers(10100, 2)) # 10.1K
print(format_numbers(1700000)) # 1.7M
print(format_numbers(1_751_000_000, 2)) # 1.75B
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文