我有以下 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的格式规范迷你语言
该函数如下所示:
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
符号,所以我只是将其从字符串中删除。
如果您有任何疑问,请随时询问。