【问题标题】:Python - Thousands separator that also works for decimals, keeping 4 significant digitsPython - 千位分隔符也适用于小数,保留 4 位有效数字
【发布时间】:2017-09-20 09:30:35
【问题描述】:

我正在使用 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

【问题讨论】:

  • 以百万单位表示价值?
  • @ReblochonMasque 这到底是什么意思?
  • 0.0001234 * 1,000,000 = 123.40 - 更容易理解和比较
  • 什么是type(value)... 例如,您是在处理整数、浮点数还是小数?
  • FWIW,您可能需要考虑 decimal i/o float 类型来处理您正在操作的值的范围以及精度的重要性

标签: python python-3.x number-formatting


【解决方案1】:

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

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

【讨论】:

  • 某些输入似乎不起作用,例如1390390000.0 返回1 390 390 0 而不是1 390 390 000463196000.0 也有问题)。如果不是这样,我绝对不介意使用这样的自定义函数(这意味着没有简单优雅的解决方案)。回到家后,我会深入研究您的代码,但我认为它可以工作。
  • @dnLL 哎呀,你是对的......我已经更改了代码,现在似乎适用于这种情况......
  • 当然似乎正在处理我现在在 API (api.coinmarketcap.com/v1/ticker/?convert=USD) 中处理的所有数字。稍后我会做更深入的测试。
  • 我看到你做了另一个编辑,但是结果似乎是一样的(这是正确的),需要解释一下区别吗?您基本上添加了 int 演员表和 decimal_numsdecimal_exp 变量。
  • @dnLL 是的,正如你所说的一样,我只是改变了如何提取小数部分字符串。我没有使用硬编码的字符串索引(由于字符串格式和逻辑,这应该是安全的,但看起来更脏)我将其更改为在e. 处拆分指数符号字符串。仍然不是很干净或任何东西,但我觉得它更舒服......
猜你喜欢
  • 2012-10-21
  • 2022-11-24
  • 1970-01-01
  • 2013-11-07
  • 2017-09-06
  • 2018-05-11
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
相关资源
最近更新 更多