如何将Decimal值调整为指定末尾数字的近似值?
解决方案
你的核心需求是找到最接近amount的数值,使其百分位数字与roundTo的百分位数字一致,而非按roundTo的间隔取整——这也是你之前尝试的步长取整方法无效的原因。
实现思路
- 把数值转换到百分位的整数维度(避免浮点数精度问题),比如
2.01转为201,0.09转为9; - 提取当前数值的百分位数字,以及目标的百分位数字(即
roundTo对应的个位数字); - 计算出上下两个候选的目标数值(比如
2.01对应199和209); - 比较两个候选与原数值的距离,选择更近的那个;若距离相等,可按需选择向上/向下取整。
完整代码
decimal amount = 2.01m; decimal roundTo = 0.09m; decimal newAmount; // 转换为百分位整数,消除小数精度问题 decimal amountScaled = amount * 100m; int targetDigit = (int)(roundTo * 100m); // 提取roundTo的百分位数字(1-9) int currentDigit = (int)(amountScaled % 10m); // 提取amount的百分位数字 // 计算上下两个候选值的百分位整数 decimal candidateLower = amountScaled - (currentDigit - targetDigit + 10) % 10; decimal candidateUpper = candidateLower + 10; // 计算与原数值的距离 decimal distanceLower = amountScaled - candidateLower; decimal distanceUpper = candidateUpper - amountScaled; // 选择更近的候选值,距离相等时默认向上取整 if (distanceLower < distanceUpper) { newAmount = candidateLower / 100m; } else if (distanceUpper < distanceLower) { newAmount = candidateUpper / 100m; } else { // 可根据需求调整为candidateLower newAmount = candidateUpper / 100m; }
测试示例
- 当
amount=2.01m,roundTo=0.09m:amountScaled=201,targetDigit=9,currentDigit=1- 候选值为
199和209,距离分别为2和8,最终newAmount=1.99m,符合预期。
- 当
amount=2.07m,roundTo=0.09m:amountScaled=207,currentDigit=7- 候选值为
199和209,距离分别为8和2,最终newAmount=2.09m,符合预期。
适配其他roundTo值
比如roundTo=0.03m,amount=2.05m:
amountScaled=205,targetDigit=3,currentDigit=5- 候选值为
203和213,距离分别为2和8,最终newAmount=2.03m。
如果amount=2.08m,roundTo=0.03m:
- 候选值为
203(距离5)和213(距离5),会默认选择2.13m,可按需调整逻辑。
内容的提问来源于stack exchange,提问作者BabaGurGur
相关产品推荐
相关产品推荐

