You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pint自定义单位时能否处理带括号的复杂运算?求解决方案

问题

首次在Pint的UnitRegistry中创建蔗糖相关的自定义单位(比重、白利度),目前仅用到加减乘运算,但带括号的运算顺序导致解析失败,想知道Pint是否支持基础运算外的复杂计算。

已定义比重单位:

PINT_UNIT_REGISTER = UnitRegistry()
PINT_UNIT_REGISTER.define('SpecificGravity = [Sucrose] = sg')

尝试定义白利度单位时出错:

PINT_UNIT_REGISTER.define('Brix = (((182.4601 * sg - 775.6821) * sg + 1262.7794) * sg - 669.5622) = bx')

错误信息:

File "/Users/aaronpaxson/PycharmProjects/stonesrivermeadery-webroot/stonesrivermeadery/settings.py", line 181, in <module>
    PINT_UNIT_REGISTER.define('Brix = (((182.4601 * sg - 775.6821) * sg + 1262.7794) * sg - 669.5622) = Bx')
File "/Users/aaronpaxson/PycharmProjects/stonesrivermeadery-webroot/venv/lib/python3.9/site-packages/pint/facets/plain/registry.py", line 428, in define
    self._helper_dispatch_adder(definition)
File "/Users/aaronpaxson/PycharmProjects/stonesrivermeadery-webroot/venv/lib/python3.9/site-packages/pint/facets/plain/registry.py", line 447, in _helper_dispatch_adder
    raise TypeError(
TypeError: No loader function defined for UnhandledParsingError
解决方法

Pint的define方法仅支持线性换算关系的单位定义,不支持这种嵌套括号的多项式非线性表达式,这是解析失败的核心原因。针对白利度(Brix)和比重(sg)的非线性换算需求,可采用以下两种可行方案:

方案1:注册双向转换函数

利用Pint的register_transformation方法,手动实现比重与白利度的双向转换逻辑:

from pint import UnitRegistry

PINT_UNIT_REGISTER = UnitRegistry()
PINT_UNIT_REGISTER.define('SpecificGravity = [Sucrose] = sg')
PINT_UNIT_REGISTER.define('Brix = [Sucrose] = bx')

# 比重转白利度
def sg_to_bx(sg_quantity):
    sg = sg_quantity.magnitude
    return ((182.4601 * sg - 775.6821) * sg + 1262.7794) * sg - 669.5622

# 白利度转比重(数值迭代求解三次方程,可根据需求优化精度)
def bx_to_sg(bx_quantity):
    bx = bx_quantity.magnitude
    sg = 1.0
    for _ in range(10):
        current_bx = ((182.4601 * sg - 775.6821) * sg + 1262.7794) * sg - 669.5622
        # 用导数做牛顿迭代加速收敛
        sg += (bx - current_bx) / (547.3803 * sg**2 - 1551.3642 * sg + 1262.7794)
    return sg

# 注册双向转换规则
PINT_UNIT_REGISTER.register_transformation(
    PINT_UNIT_REGISTER.sg, PINT_UNIT_REGISTER.bx, sg_to_bx
)
PINT_UNIT_REGISTER.register_transformation(
    PINT_UNIT_REGISTER.bx, PINT_UNIT_REGISTER.sg, bx_to_sg
)

方案2:给Quantity类扩展自定义转换方法

如果不需要全局单位转换规则,可直接给Pint的Quantity对象添加转换方法:

from pint import UnitRegistry, Quantity

PINT_UNIT_REGISTER = UnitRegistry()
PINT_UNIT_REGISTER.define('SpecificGravity = [Sucrose] = sg')
PINT_UNIT_REGISTER.define('Brix = [Sucrose] = bx')

def to_bx(self):
    if self.units != PINT_UNIT_REGISTER.sg:
        raise ValueError("仅支持比重(sg)单位转换为白利度(bx)")
    sg = self.magnitude
    bx_val = ((182.4601 * sg - 775.6821) * sg + 1262.7794) * sg - 669.5622
    return Quantity(bx_val, PINT_UNIT_REGISTER.bx)

def to_sg(self):
    if self.units != PINT_UNIT_REGISTER.bx:
        raise ValueError("仅支持白利度(bx)单位转换为比重(sg)")
    bx = self.magnitude
    sg = 1.0
    for _ in range(10):
        current_bx = ((182.4601 * sg - 775.6821) * sg + 1262.7794) * sg - 669.5622
        sg += (bx - current_bx) / (547.3803 * sg**2 - 1551.3642 * sg + 1262.7794)
    return Quantity(sg, PINT_UNIT_REGISTER.sg)

# 给Quantity类绑定方法
Quantity.to_bx = to_bx
Quantity.to_sg = to_sg

使用示例

# 比重转白利度
sg_val = PINT_UNIT_REGISTER.Quantity(1.04, 'sg')
bx_val = sg_val.to_bx()
print(bx_val)

# 白利度转比重
bx_val = PINT_UNIT_REGISTER.Quantity(10, 'bx')
sg_val = bx_val.to_sg()
print(sg_val)

内容的提问来源于stack exchange,提问作者Aaron Paxson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 09:13:22