Files

77 lines
2.2 KiB
Python

import math
from decimal import Decimal, ROUND_HALF_EVEN
def get_decimal_places(data_strings):
"""获取输入数据中小数点后的位数,用于自适应展示"""
max_places = 0
for s in data_strings:
if '.' in s:
places = len(s.split('.')[1])
max_places = max(max_places, places)
return max_places
def scientific_round(value, uncertainty):
"""
按照“四舍六入五凑偶”修约:
1. 不确定度 u 保留一位有效数字
2. 平均值/结果末位与 u 对齐
"""
if uncertainty <= 0:
return str(value), "0"
d_val = Decimal(str(value))
d_unc = Decimal(str(uncertainty))
u_float = float(d_unc)
first_digit_pos = math.floor(math.log10(u_float))
prec = Decimal('1e' + str(first_digit_pos))
u_final = d_unc.quantize(prec, rounding=ROUND_HALF_EVEN)
val_final = d_val.quantize(prec, rounding=ROUND_HALF_EVEN)
return val_final, u_final
def parse_angle_to_minutes(s):
"""
将输入解析为内部统一单位:分钟(Decimal)。
支持格式:
1. 'D.M' -> D度M分 (例如 '120.15' -> 120*60 + 15 = 7215分)
2. 'D' (纯数字无点) -> D度 (例如 '120' -> 120*60 = 7200分)
3. 'D.M.S' -> D度M分S秒 (例如 '120.15.30' -> 7215.5分)
"""
parts = s.split('.')
if len(parts) == 1:
return Decimal(parts[0]) * 60
elif len(parts) == 2:
return Decimal(parts[0]) * 60 + Decimal(parts[1])
else:
res = Decimal(parts[0]) * 60 + Decimal(parts[1])
if len(parts) >= 3:
res += Decimal(parts[2]) / 60
return res
def format_minutes_as_angle(minutes, prec=None):
"""
将总分钟数转换为 D° M' 格式,支持保持对齐精度。
"""
neg = minutes < 0
minutes = abs(minutes)
d = int(minutes // 60)
m = minutes % 60
if m >= 60:
d += 1
m -= 60
if prec is not None and prec < 1:
places = abs(prec.as_tuple().exponent)
m_str = format(m, f'.{places}f')
else:
if m == int(m):
m_str = str(int(m))
else:
m_str = format(m, 'f').rstrip('0').rstrip('.')
return f"{'-' if neg else ''}{d}°{m_str}'"