浮点数中的固定数字长度

3 投票
1 回答
1721 浏览
提问于 2025-04-18 16:30

我在网上看到很多关于这个话题的讨论,但还是找不到合适的解决办法。

我想把一些数字画出来,这些数字的长度各不相同,但我希望它们都有相同的位数。

比如说,我有:12.3456781.2345678。现在,因为我需要把它们和误差一起画出来,所以我希望每个数字的格式都不一样,以便突出它们的有效数字。

所以,我想用不同的小数位数来画这些数字。在我的情况下,画23.45678+/-1.23456没有意义,画成23.4+/-1.2更好。另一方面,我需要把1.234567+/-0.034567变成1.23+/-0.03

所以,假设我想把所有数字都画成固定宽度,可能是总共3位数字加上小数点。我应该使用类似'%1.1f' %num的方式,但我找不到正确的方法。我该怎么做呢?

1 个回答

3

我建议你定义一个类,这个类可以用来解释字符串格式化,让你得到想要的结果。
在这个类里面,你需要确定浮点数的整数部分有多长,然后用这个长度来定义合适的字符串格式。
简单来说,如果你的输入是 12.345(因为小数点前有两个数字),这个类会创建一个像 '{:4.1f}' 这样的格式;如果你的输入是 1.2345(因为小数点前只有一个数字),那么它会生成 {:4.2f} 的格式。这里的总数字位数(这个例子中是 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中将数字分成整数和小数部分
- 为字符串格式化添加自定义转换类型

撰写回答