gpt4 book ai didi

java - ASP .net C# Decimal 与 Java Double 之间的舍入不匹配

转载 作者:搜寻专家 更新时间:2023-10-30 21:31:39 25 4
gpt4 key购买 nike

我正在将 .NET 代码转换为 Java,遇到了精度不匹配的问题。

.NET代码:

private decimal roundToPrecision(decimal number, decimal roundPrecision)
{
if (roundPrecision == 0)
return number;
decimal numberDecimalMultiplier = Math.Round(number / roundPrecision, MidpointRounding.AwayFromZero);
return numberDecimalMultiplier * roundPrecision;
}

在上面的代码中调用 roundToPrecision(8.7250, 0.05); 函数得到预期的 8.75

The conversion/translation of the function to Java is as follows. I din't find exact Math.Round option.

Java代码:

public double roundToPrecision(double number, double roundPrecision) {
if (roundPrecision == 0)
return number;
int len = Double.toString(roundPrecision).split("\\.")[1].length();
double divisor = 0d;
switch (len) {
case 1:
divisor = 10d;
break;
case 2:
divisor = 100d;
break;
case 3:
divisor = 1000d;
break;
case 4:
divisor = 10000d;
break;
}
double numberDecimalMultiplier = Math.round(number / roundPrecision);
double res = numberDecimalMultiplier * roundPrecision;
return Math.round(res * divisor) / divisor;
}

在 Java 代码中调用 roundToPrecision(8.7250, 0.05); 得到 8.7,这是不正确的。

我什至尝试使用此处的引用在 Java 中使用 BigDecimal 修改代码 C# Double Rounding但没有运气。

public double roundToPrecision(double number, double roundPrecision) {
if (roundPrecision == 0)
return number;
int len = Double.toString(roundPrecision).split("\\.")[1].length();
double divisor = 0d;
switch (len) {
case 1:
divisor = 10d;
break;
case 2:
divisor = 100d;
break;
case 3:
divisor = 1000d;
break;
case 4:
divisor = 10000d;
break;
}
BigDecimal b = new BigDecimal(number / roundPrecision);
b = b.setScale(len,BigDecimal.ROUND_UP);
double numberDecimalMultiplier = Math.round(b.doubleValue());
double res = numberDecimalMultiplier * roundPrecision;
return Math.round(res * divisor) / divisor;
}

请指导我如何解决此问题。

这里有几个场景可以尝试。

  • number = 10.05;精度 = .1;预期 = 10.1;
  • number = 10.12;精度 = .01;预期 = 10.12;
  • number = 8.7250;精度 = 0.05;预期 = 8.75;
  • number = 10.999;精度 = 2;预期 = 10;
  • number = 6.174999999999999;精度 = 0.05;预期 = 6.20;

注意:我有超过 6 万个数字,精度可以从 1 位小数到 4 位小数不等。 .NET 的输出应该与 Java 完全匹配。

最佳答案

问题来自 double 与小数在内存中的存储和表示方式。有关详细信息,请参阅以下链接:Doubles Decimals

让我们看看它们在您的代码中是如何工作的。使用 double ,参数为 8.725 和 0.05。 number/roundPrecision 给出 174.499...,因为 double 无法准确表示 174.5。使用小数 number/roundPrecision 给出 174.5,小数可以准确表示。因此,当 174.499... 四舍五入时,它会四舍五入为 174 而不是 175

使用 BigDecimal 是朝着正确方向迈出的一步。但是,它在您的代码中的使用方式存在问题。当您创建 BigDecimal 值时,问题就来了。

BigDecimal b = new BigDecimal(number / roundPrecision);

BigDecimal 是从 double 创建的,因此不精确性已经存在。如果您能够从字符串创建 BigDecimal 参数,那就更好了。

public static BigDecimal roundToPrecision(BigDecimal number, BigDecimal roundPrecision) {
if (roundPrecision.signum() == 0)
return number;
BigDecimal numberDecimalMultiplier = number.divide(roundPrecision, RoundingMode.HALF_DOWN).setScale(0, RoundingMode.HALF_UP);
return numberDecimalMultiplier.multiply(roundPrecision);
}


BigDecimal n = new BigDecimal("-8.7250");
BigDecimal p = new BigDecimal("0.05");
BigDecimal r = roundToPrecision(n, p);

如果函数必须接受并返回 double 值:

public static double roundToPrecision(double number, double roundPrecision)
{
BigDecimal numberBig = new BigDecimal(number).
setScale(10, BigDecimal.ROUND_HALF_UP);
BigDecimal roundPrecisionBig = BigDecimal.valueOf(roundPrecision);
if (roundPrecisionBig.signum() == 0)
return number;
BigDecimal numberDecimalMultiplier = numberBig.divide(roundPrecisionBig, RoundingMode.HALF_DOWN).setScale(0, RoundingMode.HALF_UP);
return numberDecimalMultiplier.multiply(roundPrecisionBig).doubleValue();
}

请记住, double 不能完全表示与小数相同的值。因此,返回 double 的函数不能具有与返回小数的原始 C# 函数完全相同的输出。

关于java - ASP .net C# Decimal 与 Java Double 之间的舍入不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41644691/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com