77 lines
2.2 KiB
Python
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}'"
|