如何在python中格式化带有区域设置和指定有效小数位数的数字



我不得不使用python将数字导出为文本,并经历了几种不做我想做的事情的方法。有string.format((、旧的%string格式和F-Strings——有很多非常聪明的方法可以将东西格式化为字符串,但我找不到一种简单的方法来从符合我的标准的数字中生成字符串:

  • 区域设置中的十进制分隔符
  • 没有千位分隔符
  • 无限(~(个有效整数位数,但至少有一个零
  • 指定的有效小数位数-如果没有有效小数,则不使用小数分隔符
  • 没有科学记数法(电子记数法(

不是一个非常奇特的请求吗?我错过了什么显而易见的东西吗?

使用locale、floor和f-string可以很容易地生成所需的字符串:

import locale
locale.getdefaultlocale()
from math import floor
a = 12303123895.281789274918
a_string = f"{floor(a)}{locale.localeconv()['decimal_point']}"+f"{a-floor(a):.1g}"[2:]

打印(f"a={a_string}"(

这给了我:

a = 12303123895.3

因为我的区域设置小数分隔符是"quot;您可以通过更改":"来设置所需的小数位数。1g";至":"。Xg";,X是您想要的小数位数。

是的,我查找了一个有30年历史的Smalltalk实现。翻译非常直接,但我无法扩展PythonNumber类(在Smalltalk中很自然(。
def intlPrintRoundedMax(aNumber, decs, insigDecBool, thousBool, lZeroBool, positiveSignBool) :
"""Answer a string, the ASCII representation of the receiver rounded to decs decimal 
places using delimiters from locale.
If <insigDecBool> is false only append significant decimals.
If <thousBool> is true, insert delimiter for thousands.
If <lZeroBool> is true, a leading zero is printed.
If <positiveSignBool> add sign to positive numbers"""   
"""920416  TA  c"""
locales = locale.localeconv()
sDecimal = locales['decimal_point']
sThousand = locales['thousands_sep']
sPositiveSign = locales['positive_sign'] if positiveSignBool else ''
sNegativeSign = locales['negative_sign']
answer = ''
rounder = 10 ** decs
value = round(aNumber * rounder)
if (value < 0) :
answer += sNegativeSign
value = 0 - value
else :
if (value != 0) : answer += sPositiveSign
if (lZeroBool) :
divisor = 10 * rounder
else :
if (value == 0) : 
answer += '0' 
return answer
divisor = rounder
while (divisor <= value) :
divisor = divisor * 10
if (thousBool) :
thousands = thousandRounders = 1000 * rounder
while (thousands <= value) :
thousands = thousands * 1000
thousands = max((thousands // 1000), thousandRounders)
else : thousands = None

if (divisor == rounder) : answer += sDecimal
divisor = divisor // 10
while (divisor > 1) :
answer += chr(value // divisor + 48)
value = value % divisor
if ((not insigDecBool) and ((value == 0) and (divisor <= rounder))) :
return answer
if (divisor == thousands) :
thousands = max((thousands // 1000), thousandRounders)
answer += sThousand
if (divisor == rounder) : answer += sDecimal
divisor = divisor // 10
answer += chr(value + 48)
return answer

最新更新