当前位置: 首页 > 知识库问答 >
问题:

ASP之间的舍入不匹配。net C#十进制到Java双精度

臧彭亮
2023-03-14

我在翻译。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;
}

调用<code>roundToPrecision(8.7250,0.05) 函数提供了预期的8.75。

函数到Java的转换/翻译如下。我找不到确切的数学。圆选项。

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代码中调用roundToPreasi(8.7250, 0.05);给我8.7,这是不正确的。

我甚至尝试使用BigDecimal修改代码,如下所示Java使用此处的引用C#双舍入,但没有运气。

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完全匹配。

共有2个答案

欧阳乐生
2023-03-14

这里真正的问题是Math.round有两个定义。一个返回long,而另一个返回int!当您提供双精度时,它会运行一个long。要解决这个问题,只需将您的输入转换为浮点数,使其运行返回int的浮点数。

double numberDecimalMultiplier = Math.round((float)(number / roundPrecision));
穆宾白
2023-03-14

问题来自于双精度与小数在内存中的存储和表示方式。有关更多详细信息,请参见以下链接:双精度小数

让我们看看它们在您的代码中是如何工作的。使用double,参数为8.725和0.05<代码>数字/圆精度给出174.499 ,因为double不能准确表示174.5。用小数表示数字/舍入精度为174.5,小数可以准确地表示这一点。所以当174.499 四舍五入,它四舍五入到174,而不是175。

使用BigDecimal是朝着正确方向迈出的一步。然而,在代码中如何使用它存在一个问题。创建BigDecimal值时会出现问题。

BigDecimal b = new BigDecimal(number / roundPrecision);

bigdecimic是从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);

如果函数必须接收并返回双倍:

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#函数相同的精确输出。

 类似资料:
  • 本文向大家介绍C#浮点,双精度,十进制,包括了C#浮点,双精度,十进制的使用技巧和注意事项,需要的朋友参考一下 示例 浮动 float是.NET数据类型的别名System.Single。它允许存储IEEE 754单精度浮点数。存在此数据类型mscorlib.dll,每个C#项目在创建它们时都会隐式引用该数据类型。 大致范围:-3.4×10 38至3.4×10 38 十进制精度:6-9个有效数字 记

  • 问题内容: 如何确定整数位数和Java中类似数字的小数点后位数。 问题答案: 双精度并不总是精确的表示形式。您只能说如果将其转换为字符串,将有多少个小数位。 这仅适用于未转换为指数符号的数字。您可能会认为1.0小数点后一位或无位。

  • 所以我在学习java,两天来我一直在寻找这个问题的解决方案。我尝试了所有的十进制分隔符,并试图设置语言环境,结果发现它不起作用。 代码: 输出和错误

  • 基于此阵列: 我想在Java中打印双精度值和ascii值。我在互联网上找不到合适的解决方案。我刚刚发现如何将单个字符转换为整数值。但是很多字符呢?主要问题是,我有一个大char[]和一些双精度和int值存储在.对于双精度值,它们存储在4字节大小和整数1或2字节内,所以我必须阅读所有这些并转换为双精度或整数。 谢谢你帮忙

  • 问题内容: Angular是否具有内置指令来舍入输入值? 在这种情况下,数字过滤器不合适,因为我也想在ng-model中也舍入实际值。如果我必须写一个,那会是什么样? 问题答案: 您可以使用指令创建双向绑定转换。这是一个简单的例子: http://plnkr.co/edit/kz5QWIloxnd89RKtfkuE?p=preview 这实际上取决于您希望它如何工作。是否应该限制用户输入?您介意模

  • 问题内容: 我试图将十进制数字截断到小数位。像这样: 所做的只是正确的事情,但是却舍入了价值。我不需要四舍五入的价值。希望这是可能的JavaScript。 问题答案: 更新 : 因此,无论如何,四舍五入的bug总是会困扰着您,无论您如何努力补偿它们。因此,应该通过精确地用十进制表示法来解决该问题。 旧的易出错的解决方案基于其他人的编译: