Java中的舍入问题。为什么在这种情况下我没有得到预期的结果?

Java中的舍入问题。为什么在这种情况下我没有得到预期的结果?,java,rounding,Java,Rounding,我有一个为Minecraft制作的插件。它用于大规模的安德龙格斗,根据造成的伤害在每个人之间公平分配经验 这是可行的,但有一个小问题,使方程式失去了经验 代码如下: private void divideExpAmongstPlayersBasedOnDamageDealt(int exp, Map<Player, Double> damageMap) { double totalDamageDealt = 0.0d; for (Double value : dam

我有一个为Minecraft制作的插件。它用于大规模的安德龙格斗,根据造成的伤害在每个人之间公平分配经验

这是可行的,但有一个小问题,使方程式失去了经验

代码如下:

private void divideExpAmongstPlayersBasedOnDamageDealt(int exp, Map<Player, Double> damageMap) {
    double totalDamageDealt = 0.0d;

    for (Double value : damageMap.values()) {
        totalDamageDealt += value;
    }

    while (exp > 0 && !damageMap.isEmpty()) {
        Player maxHitterInList = Collections.max(damageMap.entrySet(),
                Comparator.comparingDouble(Map.Entry::getValue)).getKey();

        double damageShare = damageMap.get(maxHitterInList) / totalDamageDealt;
        int expShare = (int) Math.round(exp * damageShare);

        if (expShare == 0)
            break;

        if (maxHitterInList.isOnline()) {
            sendPlayerMessage(maxHitterInList, damageShare, expShare);
            maxHitterInList.giveExp(expShare);
        }

        exp -= expShare;

        damageMap.remove(maxHitterInList);
    }
}
private void divideexpamongstplayersbasedondamagedemand(int-exp,Map-damageMap){
双重总损伤处理=0.0d;
for(双值:damageMap.values()){
总损坏处理+=值;
}
而(exp>0&!damageMap.isEmpty()){
Player maxHitterInList=Collections.max(damageMap.entrySet(),
Comparator.comparingDouble(Map.Entry::getValue)).getKey();
double damageShare=damageMap.get(maxHitterInList)/TotalDamageDealed;
int expShare=(int)Math.round(exp*damageShare);
if(expShare==0)
打破
if(maxHitterInList.isOnline()){
sendPlayerMessage(maxHitterInList、damageShare、expShare);
maxHitterInList.giveExp(expShare);
}
exp-=expShare;
damageMap.remove(maxHitterInList);
}
}
它会找到最大打击者,奖励他们的经验份额,并将他们从列表中删除,直到没有更多的经验可以提供

问题是它没有抓住要点,迫使我添加
&&!damageMap.isEmpty()
将其设置为while条件以避免异常。。它总是准确地打印百分比(总和为100)

我认为这与Math.round函数有关,尽管我不知道如何调试这个函数。当我手工计算时,它们就计算出来了

例如(这确实发生了):一个暴民给予
10
exp.玩家1造成了
57%
的伤害,玩家2造成了
43%
。百分比值打印正确,但Player1接收
6
EXP,Player2接收
2
??上次我检查了
0.57*10
equals
5.7=6
0.43*10
equals
4.3=4

我错过了什么?这与圆函数或双倍运算的方式有关吗


谢谢

这不是舍入问题,但您在计算中使用了错误的值

你写了“上次我检查0.57*10等于5.7=6,0.43*10等于4.3=4”,但你使用的公式是

int expShare = (int) Math.round(exp * damageShare);
对于循环的每次迭代,都要更新
exp

exp -= expShare;
这意味着对于你的第二个玩家来说,exp是4,而不是你在例子中假设的10,所以实际计算是0.43*2,四舍五入为2


因此,您需要将while条件中使用的变量与计算中使用的变量分开。

这不是舍入问题,但您在计算中使用了错误的值

你写了“上次我检查0.57*10等于5.7=6,0.43*10等于4.3=4”,但你使用的公式是

int expShare = (int) Math.round(exp * damageShare);
对于循环的每次迭代,都要更新
exp

exp -= expShare;
这意味着对于你的第二个玩家来说,exp是4,而不是你在例子中假设的10,所以实际计算是0.43*2,四舍五入为2


因此,您需要将
while
条件中使用的变量与计算中使用的变量分开。

一个好的技巧是将方法参数声明为final,这样它们就永远不会被更新,每当需要更新时,您就复制并使用它。一个好的技巧是将方法参数声明为final,这样它们就永远不会被更新已更新,无论何时需要更新,都要制作一份副本并使用它。