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

价格联动计算精度异常求助:输入零售价后数值偏差

问题分析与解决方案

问题根源

精度偏差的核心原因是多次链式调用Math.Round导致误差累积:

  • 从零售价反向计算时,先将批发价四舍五入到两位小数,再用这个已丢失精度的批发价计算成本价并再次四舍五入,两次舍入的微小误差叠加后,最终结果偏离了原始值。
  • 部分计算中使用整数运算(如100+15),触发隐式类型转换,也会引入额外精度风险。

修复方案

核心思路:仅在最终赋值给实体字段时进行一次四舍五入,中间计算保留完整的decimal精度,避免链式舍入的误差累积。同时统一使用decimal类型字面量(加m后缀),消除整数运算的隐式转换问题。

修改后的代码示例

private decimal CostPrice
{
    get => SelectedItem.Cost;
    set
    {
        SelectedItem.Cost = value;
        
        // 先计算高精度批发价,不提前round
        decimal wholesalePrice = (((SelectedItem.Cost + SelectedItem.Transport + SelectedItem.RoyaltyMarket + SelectedItem.DelStrand) 
                                  / (1 - SelectedItem.Margin) * (1 + SelectedItem.AdjPercentage)) 
                                 + SelectedItem.Levy);
        SelectedItem.WholesalePrice = Math.Round(wholesalePrice, 2);
        
        // 用高精度批发价计算零售价,最后统一round
        decimal retailPrice = ((wholesalePrice / (1m - 0.23m)) * (100m + 15m) / 100m) / SelectedItem.StockUom;
        SelectedItem.RecRetailPrice = Math.Round(retailPrice, 2);
    }
}

private decimal WholesalePrice
{
    get => SelectedItem.WholesalePrice;
    set
    {
        SelectedItem.WholesalePrice = value;
        
        decimal retailPrice = ((value / (1m - 0.23m)) * (100m + 15m) / 100m) / SelectedItem.StockUom;
        SelectedItem.RecRetailPrice = Math.Round(retailPrice, 2);
        
        // 用原始输入的批发价直接计算成本,中间不做round
        decimal costPrice = (((value - SelectedItem.Levy) / (1m + SelectedItem.AdjPercentage)) 
                            * (1m - SelectedItem.Margin) 
                           - SelectedItem.Transport - SelectedItem.RoyaltyMarket - SelectedItem.DelStrand);
        SelectedItem.Cost = Math.Round(costPrice, 2);
    }
}

private decimal RecRetailPrice
{
    get => SelectedItem.RecRetailPrice;
    set
    {
        SelectedItem.RecRetailPrice = value;
        
        // 计算高精度批发价,不提前round
        decimal wholesalePrice = ((value * (1m - 0.23m)) / (100m + 15m) * 100m) * SelectedItem.StockUom;
        SelectedItem.WholesalePrice = Math.Round(wholesalePrice, 2);
        
        // 直接用高精度批发价计算成本,避免依赖已round的中间值
        decimal costPrice = (((wholesalePrice - SelectedItem.Levy) / (1m + SelectedItem.AdjPercentage)) 
                            * (1m - SelectedItem.Margin) 
                           - SelectedItem.Transport - SelectedItem.RoyaltyMarket - SelectedItem.DelStrand);
        SelectedItem.Cost = Math.Round(costPrice, 2);
    }
}

额外优化建议

  • 将重复的计算逻辑(如成本转批发价、批发价转成本价等)提取为独立私有方法,减少代码冗余,方便后续维护。
  • 确认SelectedItem中的所有价格相关字段均为decimal类型,避免使用float/double这类浮点类型带来的精度损失。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 18:43:12