以最高精度将数字格式化为 8 或 16 个字符(不含“e”)

问题描述 投票:0回答:1

我有以下 python 程序。 输入是任何数字(来自计算)和格式,其中格式可以是“长”或“短”

我想做的事: 如果格式很短,我希望输出是输入的数字,但最多使用 8 个字符(包括符号)。如果格式很长,输出最多可能使用 16 个字符。 只有负数前面必须有“-”。仅当科学格式提高“缩短”数字的数值精度时,才必须在结果中使用科学格式。 如果输出科学数,则不能使用“e”,因为它占用了不必要的空间:

我的proc已经被延长了好几次,并不能满足所有情况下的要求。

任何人都可以帮助我以良好的方式实现所需的输出吗?

def format_nastran(number, format):
if format == "free":
    return number
if format == "short":
    fieldsize = 8
if format == "long":
    fieldsize = 16

charsfor_comma = 1

# Help functions ##########################################################
def remove_trailing_zeros(number):
    # Convert to string, strip trailing zeros, and convert back to number
    stripped_number = str(number).rstrip('0').rstrip('.') if '.' in str(number) else str(number)
    return type(number)(stripped_number)

def count_decimals(number):
    # Convert to string
    number_str = str(number)

    # Check if the string contains a decimal point
    if '.' in number_str:
        # Get the portion after the decimal point and count its length
        decimal_part = number_str.split('.')[1]
        return len(decimal_part)
    else:
        return 0  # No decimals


# #########################################################################


scientific = str(number).find("e")

# Case 1 Integer which fits into the field without any changes
# short format: 12345678
# short format: -1234567
# long format : 1234567812345678
# long format : -123456781234567
if scientific == -1:
    number = remove_trailing_zeros(number)
    num_chars = len(str(number))
    if num_chars <= fieldsize:
        return number
# Case 2 Integer which is to large to fit into the field, has to be converted to scientific format
# short format: 1234567891
# short format: -123456789
# long format : 123456781234567812345678
# long format : -12345678123456781234567
    if num_chars > fieldsize:
        e_number = "{:.12e}".format(float(number))
        # Split the number into mantissa and exponent
        mantissa, exponent = e_number.split("e")
        # Strip leading zeros from exponent
        exponent = int(exponent)
        if int(exponent) > 0:
            exponent = "+" + str(exponent)
        charsinexponent = len(str(exponent))
        # determine the length of the mantissa
        mantissa = remove_trailing_zeros(mantissa)
        charsmantissa = len(str(mantissa))
        # determine number of decimals
        charsdezimals = count_decimals(mantissa)
        # determine number of chars before dezimals
        chars_intpart = charsmantissa - charsdezimals - charsfor_comma
        # To how many numbers do weh have  to round the mantissa so that mantissa plus exponent fits into the field?
        round_to = fieldsize - chars_intpart - charsfor_comma - charsinexponent
        if round_to > 0:
            rounded_mantissa = round(float(mantissa),round_to)
            # assemble the whole number
            formatted_number = str(rounded_mantissa) + str(exponent)
        else:
            formatted_number = str(mantissa) + str(exponent)

        return formatted_number




if scientific != -1:
# Case 3 Scientific number which fits into the field without an changes after the 'e' and unneccesary leading 0 of the exponent has been removed
# short format: 1.2345e-005  -> 1.2345-5     3 signs gain
# short format: -1.234e-005  -> -1.234-5
# long format :
# long format :
    mantissa, exponent = str(number).split("e")
    # Strip leading zeros from exponent
    exponent = int(exponent)
    if int(exponent) > 0:
        exponent = "+" + str(exponent)
    charsinexponent = len(str(exponent))
    # determine the length of the mantissa
    mantissa = remove_trailing_zeros(mantissa)
    charsmantissa = len(str(mantissa))
    # determine number of decimals
    charsdezimals = count_decimals(mantissa)
    # determine number of chars before dezimals
    chars_intpart = charsmantissa - charsdezimals - charsfor_comma
    # To how many numbers do we have  to round the mantissa so that mantissa plus exponent fits into the field?
    round_to = fieldsize - chars_intpart - charsfor_comma - charsinexponent
    if round_to > 0:
        rounded_mantissa = round(float(mantissa),round_to)
        # assemble the whole number
        formatted_number = str(rounded_mantissa) + str(exponent)
    else:
        formatted_number = str(mantissa) + str(exponent)

    return formatted_number

测试数据:

#number = 30000000000000.0
#number = 123456789123456789
#number = -123456789123456789
#number = 12345678
number = -12345678  # The question here is if it not better to simply round instead of switching to scientific format...
#number = 6.5678e-06
#number = 6.5678999e-06
#number = 6.5678123456789123e-000006
#number = 6.5678123456789123e-000006
#number = 6.5678123456789123e+000006
#number = -6.5678123456789123e-06
#format = 'long'
format = 'short'
result = format_nastran(number, format)
print(str(result))
python formatting numbers rounding precision
1个回答
1
投票

您可以使用Python的格式规范迷你语言

该函数如下所示:

def format_custom(number: int | float, format_: str) -> str:
    if format_ == "short":
        max_length = 8
    elif format_ == "long":
        max_length = 16
    else:
        raise RuntimeError(f"Unrecognized format : '{format_}'")

    # Space used for the mantissa, period, exponent sign, exponent and optional negative sign
    used_space = 4 + (number < 0)

    return f"{number:-.{max_length - used_space}g}".replace("e", "")

我在一些输入上测试了它:

print(format_custom(123456789, "short"))
print(format_custom(123456789, "long"))
print(format_custom(-123456789, "short"))
print(format_custom(-123456789, "long"))
print(format_custom(123456789123456789, "short"))
print(format_custom(123456789123456789, "long"))
print(format_custom(-123456789123456789, "short"))
print(format_custom(-123456789123456789, "long"))

它是如何工作的?

大部分逻辑发生在 f 字符串中

f"{number:-.{max_length - used_space}g}"

-
符号表示如果我们的数字为负数,则应使用减号。

老实说,我找不到

.
的作用,但没有它它就无法工作。如果有人能插话并解释那就太好了。

{max_length - used_space}
计算出的数字是我们的结果允许采用的字符数。
used_space
是尾数、句点、指数符号、指数本身和可选负号使用的空格数。

g
表示如果数字已经符合我们的长度标准,则不应使用科学计数法。

我找不到一种方法来不使用格式化语言获取

e
符号,所以我只是将其从字符串中删除。


如果您有任何疑问,请随时询问。

© www.soinside.com 2019 - 2024. All rights reserved.