Python 千位分隔符,也适用于小数,保留 4 位有效数字

2024-10-02 14:26:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用一个API来获取加密货币(https://api.coinmarketcap.com/v1/ticker/?convert=USD)的数据,正如你们中的一些人可能知道的,加密货币的价值可能超过4000美元(BTC),或者对于其他一些货币,可能低于0.000001美元。我必须工作,轻松地比较所有这些数字。你知道吗

在加拿大,我们使用空格字符作为千位分隔符。我希望它能对成千上万的人起作用,但也能对小数位数进行分组。另外,我需要一种方法,只保留一些重要的数字。以比特币为例,我不想要小数部分。我希望总是有至少4个有效数字,这基本上意味着,如果number >= 1000,我不需要小数部分(但我保留完整的整数部分),如果是< 0,我希望在第一个非零数字之后至少有3个额外的数字(如果需要的话,可以四舍五入)。你知道吗

输入示例=>;我想要的输出:

65410845186.1      => 65 410 845 186
43245.1            => 43 245
285.1234           => 285.1
0.01234567         => 0.123 5
0.001234054        => 0.001 234
0.001034538        => 0.001 035
0.00010001         => 0.000 100 0
1                  => 1.000
1.0006             => 1.001

脚本需要在不同的操作系统上工作。我不认为任何locale或琐碎的format实现可以在这里工作。在保留4位有效数字(必要时进行舍入)的同时,用一个点作为十进制分隔符,以两种方式添加空格分隔符的最佳方法是什么?除了保留整数部分的数字>= 1000?你知道吗

我从StackOverflow上找到的另一段代码中使用了空间分隔符作为千位分隔符:

def splitThousands(s, tSep=' ', dSep=','):
    if s.rfind('.')>0:
        rhs=s[s.rfind('.')+1:]
        s=s[:s.rfind('.')]
        if len(s) <= 3: return s + dSep + rhs
        return splitThousands(s[:-3], tSep) + tSep + s[-3:] + dSep + rhs
    else:
        if len(s) <= 3: return s
        return splitThousands(s[:-3], tSep) + tSep + s[-3:]

但是,它不考虑有效位数,也不为小数部分添加分隔符。你知道吗

注意:这些值波动很大,我确实不介意非常极端的情况,1.0004999999999的浮点值会四舍五入到1.001。你知道吗


Tags: 方法lenreturnif货币数字整数空格
1条回答
网友
1楼 · 发布于 2024-10-02 14:26:31

不完全是一个干净或直接的解决方案,但这里有一个适合的功能:

from math import floor, log10

def format_btc(value, tSep=' ', dSep='.', precision=4, grouping=3):
    int_digits = max(int(floor(log10(value))) + 1, 0)
    if int_digits >= precision:
        int_part = int(round(value))
        decimal_part = None
    else:
        int_part = int(floor(value))
        decimal_part = value % 1.0
    int_str = str(int_part)[::-1]
    int_str = [int_str[i:i + grouping][::-1]
               for i in range(0, len(int_str), grouping)]
    int_str = tSep.join(reversed(int_str))
    if decimal_part is None:
        return int_str
    if int_digits > 0:
        num_decimals = precision - int_digits
    else:
        decimal_str = "{:.{precision}e}".format(decimal_part, precision=precision - 1)
        decimal_pos = -int(decimal_str.split("e")[1])
        num_decimals = decimal_pos + precision - 1
    decimal_str = "{:.{precision}f}".format(decimal_part, precision=num_decimals)
    decimal_str = decimal_str.split(".")[1]
    if int_digits > 0:
        decimal_str = decimal_str[:precision - int_digits]
    decimal_str = [decimal_str[i:i + grouping] for i in range(0, len(decimal_str), grouping)]
    decimal_str = tSep.join(decimal_str)
    return dSep.join((int_str, decimal_str))

tests = [65410845186.123456, 4324.1, 285.1234, 0.01234567, 0.001234054,
         0.001034538, 0.00010001, 1390390000.0, 1.0006]

for test in tests:
    print("{:<20f} => {:s}".format(test, format_btc(test)))

输出:

65410845186.123459   => 65 410 845 186
4324.100000          => 4 324
285.123400           => 285.1
0.012346             => 0.012 35
0.001234             => 0.001 234
0.001035             => 0.001 035
0.000100             => 0.000 100 0
1390390000.000000    => 1 390 390 000
1.000600             => 1.001

相关问题 更多 >