浮点数中的固定位数数字

3

我在SE上看到了很多关于这个问题的讨论,但是还没有找到合适的方法。

我想绘制一些数字,这些数字长度不同,但要求有相同的位数。

例如,我有:12.3456781.2345678。现在,由于我需要将它们与其误差一起绘制,所以我希望每个数字都有不同的格式,以便它们具有重要性。

因此,我希望用可变的小数点位数来绘制它们。在我的情况下,绘制23.45678+/-1.23456没有意义,而更好的方式是23.4+/-1.2。另一方面,我需要1.234567+/-0.034567变成1.23+/-0.03

所以,假设我想用固定宽度来绘制所有数字,可能是总共3个数字加上逗号。我应该使用类似于'%1.1f'%num的东西,但我找不到正确的方法。我该怎么做?


@Schorsch,不完全是这样。问题在于,在我的情况下,小数位数是可变的,根据整数部分和值的误差而定。我只需要固定总位数而不是小数位数。 - Py-ser
@Schorsch,在你的例子中,我需要提前知道小数位数,但实际情况并非如此,而且我还需要在代码中添加更多变量(DECIMALS列表)。相反,我更喜欢一个“自洽”的解决方案,即根据其特性自动排列格式。 - Py-ser
1个回答

3

我建议定义一个类来解释字符串格式化,以获得你想要的结果。
在这个类中,你可以确定浮点数整数部分的长度,并使用它来定义适当的字符串格式。
简而言之,该类创建了一个格式化程序,例如'{:4.1f}',如果您的输入是12.345(因为在小数分隔符之前有两位数字),则会创建{:4.2f},如果您的输入是1.2345(因为在小数分隔符之前只有一位数字)。总位数(在此示例中为4)作为输入提供。
新的格式化程序为:{:nQ},其中n是总位数(因此在上面的示例中,您将指定{:4Q}以获得所需的输出。
以下是代码:

import math

class IntegerBasedFloat(float):
    def __format__(self, spec):
        value = float(self)

        # apply the following only, if the specifier ends in Q
        # otherwise, you maintain the original float format
        if spec.endswith('Q'):
            # split the provided float into the decimal 
            # and integer portion (for this math is required):
            DEC, INT = math.modf(value)

            # determine the length of the integer portion:
            LEN = len(str(abs(int(INT))))

            # calculate the number of available decimals 
            # based on the overall length
            # the -1 is required because the separator 
            # requires one digit
            DECIMALS = int(spec[-2]) - LEN - 1

            if DECIMALS < 0:
                print 'Number too large for specified format'
            else:
                # create the corresponding float formatter
                # that can be evaluated as usual:
                spec = spec[-2] + '.' + str(DECIMALS) + 'f'

        return format(value, spec)

DATA = [12.345, 2.3456, 345.6789]

print '{:4Q}'.format(IntegerBasedFloat(DATA[0]))
print '{:4Q}'.format(IntegerBasedFloat(DATA[1]))
print '{:4Q}'.format(IntegerBasedFloat(DATA[2]))
print 'This is a "custom" float: {:5Q} and a "regular" float: {:5.3f}'.format(IntegerBasedFloat(12.3456),12.3456)

输出应为:
12.3
2.35
 346
This is a "custom" float: 12.35 and a "regular" float: 12.346

这个答案的灵感来自:
- 如何在Python中将数字分成整数和小数部分
- 为字符串格式添加自定义转换类型


1
@downvoter 你介意解释一下为什么这个答案不太有帮助,它没有回答问题或者有什么错误吗?我特别想知道如果这个建议有什么不良副作用。 - Schorsch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接