Java:如何为double值设置Precision? [重复]

时间:2021-11-27 17:09:57

This question already has an answer here:

这个问题在这里已有答案:

I was working with numbers recently and I had a situation where I want to set the precision of a double value say to 6 digits or 4 digits, depending on the value stored in the database.

我最近正在处理数字,我有一种情况,我希望将双精度值的精度设置为6位数或4位数,具体取决于数据库中存储的值。

For example, If in the database the precision is set as 4 digits then the output must look as,

例如,如果在数据库中精度设置为4位,则输出必须为,

10.0000.

10.0000。

I tried with DecimalFormat and using the string ##.####, but it is annoying to use symbols everytime.

我尝试使用DecimalFormat并使用字符串##。####,但每次使用符号都很烦人。

Is there any better approach, say something like below:

有没有更好的方法,如下所示:

Double value = 10.0;
value.setPrecision(4);

12 个解决方案

#1


43  

You can't set the precision of a double (or Double) to a specified number of decimal digits, because floating-point values don't have decimal digits. They have binary digits.

您不能将double(或Double)的精度设置为指定的十进制数,因为浮点值不具有十进制数字。他们有二进制数字。

You will have to convert into a decimal radix, either via BigDecimal or DecimalFormat, depending on what you want to do with the value later.

您必须通过BigDecimal或DecimalFormat转换为十进制基数,具体取决于您稍后要对该值执行的操作。

See also my answer to this question for a refutation of the inevitable *100/100 answers.

另请参阅我对这个问题的回答,以反驳不可避免的* 100/100答案。

#2


218  

You can try BigDecimal for this purpose

您可以为此目的尝试BigDecimal

Double toBeTruncated = new Double("3.5789055");

Double truncatedDouble = BigDecimal.valueOf(toBeTruncated)
    .setScale(3, RoundingMode.HALF_UP)
    .doubleValue();

#3


43  

this is a easy way to do it.

这是一种简单的方法。

String formato = String.format("%.2f");

it set the presition to 2 digit o any.

它将预定设置为2位数o任意。

if you only want to print it use this way.

如果你只想用这种方式打印它。

System.out.printf("%.2f",123.234);

#4


6  

To set precision for double values DecimalFormat is good technique. To use this class import java.text.DecimalFormat and create object of it for example

为double值设置精度DecimalFormat是一种很好的技术。要使用此类,请导入java.text.DecimalFormat并创建它的对象

double no=12.786;
DecimalFormat dec = new DecimalFormat("#0.00");
System.out.println(dec.format(no));

So it will print two digits after decimal point here it will print 12.79

因此它将在小数点后打印两位数字,它将打印12.79

#5


5  

This worked for me:

这对我有用:

public static void main(String[] s) {
        Double d = Math.PI;
        d = Double.parseDouble(String.format("%.3f", d));  // can be required precision
        System.out.println(d);
    }

#6


3  

The precision of double and float is fixed by their size and the way the IEEE floating point types are implemented.

double和float的精度由它们的大小和IEEE浮点类型的实现方式决定。

The number of decimal digits in the output, on the other hand, is a matter of formatting. You are correct that typing the same constant over and over is a bad idea. You should declare a string constant instead, and use its symbolic representation.

另一方面,输出中的小数位数是格式化的问题。你是正确的,一遍又一遍地输入相同的常数是个坏主意。您应该声明一个字符串常量,并使用其符号表示。

private static final String DBL_FMT = "##.####";

Using a symbolic representation would let you change precision in all places the constant is used without searching through your code.

使用符号表示可以让您在不使用代码搜索常量的所有位置更改精度。

#7


2  

Here's an efficient way of achieving the result with two caveats.

这是一个实现结果的有效方法,有两点需要注意。

  1. Limits precision to 'maximum' N digits (not fixed to N digits).
  2. 将精度限制为“最大”N位(不固定为N位)。
  3. Rounds down the number (not round to nearest).
  4. 向下舍入数字(不是舍入到最近)。

See sample test cases here.

请在此处查看示例测试用例

123.12345678 ==> 123.123
1.230000 ==> 1.23
1.1 ==> 1.1
1 ==> 1.0
0.000 ==> 0.0
0.00 ==> 0.0
0.4 ==> 0.4
0 ==> 0.0
1.4999 ==> 1.499
1.4995 ==> 1.499
1.4994 ==> 1.499

Here's the code. The two caveats I mentioned above can be addressed pretty easily, however, speed mattered more to me than accuracy, so i left it here. String manipulations like System.out.printf("%.2f",123.234); are computationally costly compared to mathematical operations. In my tests, the below code (without the sysout) took 1/30th the time compared to String manipulations.

这是代码。我上面提到的两个警告可以很容易地解决,然而,速度对我来说比准确性更重要,所以我把它留在这里。字符串操作,如System.out.printf(“%。2f”,123.234);与数学运算相比,计算成本高。在我的测试中,与String操作相比,下面的代码(没有sysout)花费了1/30的时间。

public double limitPrecision(String dblAsString, int maxDigitsAfterDecimal) {
    int multiplier = (int) Math.pow(10, maxDigitsAfterDecimal);
    double truncated = (double) ((long) ((Double.parseDouble(dblAsString)) * multiplier)) / multiplier;
    System.out.println(dblAsString + " ==> " + truncated);
    return truncated;
}

#8


1  

BigDecimal value = new BigDecimal(10.0000);
value.setScale(4);

#9


0  

To expand on @EJP, the concept of 'precision' when dealing with doubles is extremely fraught. As discussed in https://*.com/a/3730040/390153 you can't even represent 0.1 as a double regardless of the precision, for the same reason you can't represent 1/3 in base 10 with finite precision.

为了扩展@EJP,处理双打时“精确”的概念非常令人担忧。正如在https://*.com/a/3730040/390153中所讨论的那样,无论精度如何,你都不能将0.1表示为双精度,因为同样的原因你不能用有限精度表示基数10的1/3。

You need to consider the problem you are trying to solve, and consider:

您需要考虑您要解决的问题,并考虑:

a) Should I be using doubles in the first place; if precision is a relevant concept, then using doubles may well be a mistake.

a)我应该首先使用双打;如果精确度是一个相关的概念,那么使用双精度可能是一个错误。

b) If doubles are appropriate, what do I mean by precision? If you are only talking about display, wrap the logic in a display function and you will only need to deal with it in one place; ie. apply the DRY principle.

b)如果双打是合适的,精确度是什么意思?如果您只是谈论显示,请将逻辑包装在显示功能中,您只需要在一个地方处理它;即。应用DRY原则。

#10


0  

I saw the answer at top:

我在顶部看到了答案:

Double toBeTruncated = new Double("3.5789055");
Double truncatedDouble = BigDecimal.valueOf(toBeTruncated)
    .setScale(3, RoundingMode.HALF_UP)
    .doubleValue();

which i think is not the perfect answer. Because answer will change when you call .doubleValue() in many cases. Example: output of BigDecimal.valueOf(toBeTruncated) .setScale(3, RoundingMode.HALF_UP) is 12.500

我认为这不是完美的答案。因为在许多情况下调用.doubleValue()时,答案会发生变化。示例:BigDecimal.valueOf(toBeTruncated).setScale(3,RoundingMode.HALF_UP)的输出为12.500

then after .doubleValue(), the output will be 12.5 i.e. precision is lost.

然后在.doubleValue()之后,输出将为12.5,即精度丢失。

Solution either use BigDecimal type without .doubleValue() method to display or use string formatting after the final answer

解决方案要么使用BigDecimal类型而不使用.doubleValue()方法,要么在最终答案后显示或使用字符串格式

#11


-1  

Maybe this method would help you for precising double values.

也许这种方法可以帮助你精确化双重值。

double truncate(double number)
    {
        int integerPart = (int) number;
        double fractionalPart = number - integerPart;
        fractionalPart *= 100;  //It is for upto two decimal values after point.
                                //You can increase the zeros to fulfill your needs.
        int fractPart = (int) fractionalPart;
        fractionalPart = (double) (integerPart) + (double) (fractPart)/100;
        return fractionalPart;
    }

This method will allow to set the precision level.

此方法将允许设置精度级别。

double truncate(double number, int precision)
{
    double prec = Math.pow(10, precision);
    int integerPart = (int) number;
    double fractionalPart = number - integerPart;
    fractionalPart *= prec;
    int fractPart = (int) fractionalPart;
    fractionalPart = (double) (integerPart) + (double) (fractPart)/prec;
    return fractionalPart;
}

#12


-1  

public static String setPrecision(String number, int decimal) {
    double nbr = Double.valueOf(number);
    int integer_Part = (int) nbr;
    double float_Part = nbr - integer_Part;
    int floating_point = (int) (Math.pow(10, decimal) * float_Part);
    String final_nbr = String.valueOf(integer_Part) + "." + String.valueOf(floating_point);
    return final_nbr;
}

#1


43  

You can't set the precision of a double (or Double) to a specified number of decimal digits, because floating-point values don't have decimal digits. They have binary digits.

您不能将double(或Double)的精度设置为指定的十进制数,因为浮点值不具有十进制数字。他们有二进制数字。

You will have to convert into a decimal radix, either via BigDecimal or DecimalFormat, depending on what you want to do with the value later.

您必须通过BigDecimal或DecimalFormat转换为十进制基数,具体取决于您稍后要对该值执行的操作。

See also my answer to this question for a refutation of the inevitable *100/100 answers.

另请参阅我对这个问题的回答,以反驳不可避免的* 100/100答案。

#2


218  

You can try BigDecimal for this purpose

您可以为此目的尝试BigDecimal

Double toBeTruncated = new Double("3.5789055");

Double truncatedDouble = BigDecimal.valueOf(toBeTruncated)
    .setScale(3, RoundingMode.HALF_UP)
    .doubleValue();

#3


43  

this is a easy way to do it.

这是一种简单的方法。

String formato = String.format("%.2f");

it set the presition to 2 digit o any.

它将预定设置为2位数o任意。

if you only want to print it use this way.

如果你只想用这种方式打印它。

System.out.printf("%.2f",123.234);

#4


6  

To set precision for double values DecimalFormat is good technique. To use this class import java.text.DecimalFormat and create object of it for example

为double值设置精度DecimalFormat是一种很好的技术。要使用此类,请导入java.text.DecimalFormat并创建它的对象

double no=12.786;
DecimalFormat dec = new DecimalFormat("#0.00");
System.out.println(dec.format(no));

So it will print two digits after decimal point here it will print 12.79

因此它将在小数点后打印两位数字,它将打印12.79

#5


5  

This worked for me:

这对我有用:

public static void main(String[] s) {
        Double d = Math.PI;
        d = Double.parseDouble(String.format("%.3f", d));  // can be required precision
        System.out.println(d);
    }

#6


3  

The precision of double and float is fixed by their size and the way the IEEE floating point types are implemented.

double和float的精度由它们的大小和IEEE浮点类型的实现方式决定。

The number of decimal digits in the output, on the other hand, is a matter of formatting. You are correct that typing the same constant over and over is a bad idea. You should declare a string constant instead, and use its symbolic representation.

另一方面,输出中的小数位数是格式化的问题。你是正确的,一遍又一遍地输入相同的常数是个坏主意。您应该声明一个字符串常量,并使用其符号表示。

private static final String DBL_FMT = "##.####";

Using a symbolic representation would let you change precision in all places the constant is used without searching through your code.

使用符号表示可以让您在不使用代码搜索常量的所有位置更改精度。

#7


2  

Here's an efficient way of achieving the result with two caveats.

这是一个实现结果的有效方法,有两点需要注意。

  1. Limits precision to 'maximum' N digits (not fixed to N digits).
  2. 将精度限制为“最大”N位(不固定为N位)。
  3. Rounds down the number (not round to nearest).
  4. 向下舍入数字(不是舍入到最近)。

See sample test cases here.

请在此处查看示例测试用例

123.12345678 ==> 123.123
1.230000 ==> 1.23
1.1 ==> 1.1
1 ==> 1.0
0.000 ==> 0.0
0.00 ==> 0.0
0.4 ==> 0.4
0 ==> 0.0
1.4999 ==> 1.499
1.4995 ==> 1.499
1.4994 ==> 1.499

Here's the code. The two caveats I mentioned above can be addressed pretty easily, however, speed mattered more to me than accuracy, so i left it here. String manipulations like System.out.printf("%.2f",123.234); are computationally costly compared to mathematical operations. In my tests, the below code (without the sysout) took 1/30th the time compared to String manipulations.

这是代码。我上面提到的两个警告可以很容易地解决,然而,速度对我来说比准确性更重要,所以我把它留在这里。字符串操作,如System.out.printf(“%。2f”,123.234);与数学运算相比,计算成本高。在我的测试中,与String操作相比,下面的代码(没有sysout)花费了1/30的时间。

public double limitPrecision(String dblAsString, int maxDigitsAfterDecimal) {
    int multiplier = (int) Math.pow(10, maxDigitsAfterDecimal);
    double truncated = (double) ((long) ((Double.parseDouble(dblAsString)) * multiplier)) / multiplier;
    System.out.println(dblAsString + " ==> " + truncated);
    return truncated;
}

#8


1  

BigDecimal value = new BigDecimal(10.0000);
value.setScale(4);

#9


0  

To expand on @EJP, the concept of 'precision' when dealing with doubles is extremely fraught. As discussed in https://*.com/a/3730040/390153 you can't even represent 0.1 as a double regardless of the precision, for the same reason you can't represent 1/3 in base 10 with finite precision.

为了扩展@EJP,处理双打时“精确”的概念非常令人担忧。正如在https://*.com/a/3730040/390153中所讨论的那样,无论精度如何,你都不能将0.1表示为双精度,因为同样的原因你不能用有限精度表示基数10的1/3。

You need to consider the problem you are trying to solve, and consider:

您需要考虑您要解决的问题,并考虑:

a) Should I be using doubles in the first place; if precision is a relevant concept, then using doubles may well be a mistake.

a)我应该首先使用双打;如果精确度是一个相关的概念,那么使用双精度可能是一个错误。

b) If doubles are appropriate, what do I mean by precision? If you are only talking about display, wrap the logic in a display function and you will only need to deal with it in one place; ie. apply the DRY principle.

b)如果双打是合适的,精确度是什么意思?如果您只是谈论显示,请将逻辑包装在显示功能中,您只需要在一个地方处理它;即。应用DRY原则。

#10


0  

I saw the answer at top:

我在顶部看到了答案:

Double toBeTruncated = new Double("3.5789055");
Double truncatedDouble = BigDecimal.valueOf(toBeTruncated)
    .setScale(3, RoundingMode.HALF_UP)
    .doubleValue();

which i think is not the perfect answer. Because answer will change when you call .doubleValue() in many cases. Example: output of BigDecimal.valueOf(toBeTruncated) .setScale(3, RoundingMode.HALF_UP) is 12.500

我认为这不是完美的答案。因为在许多情况下调用.doubleValue()时,答案会发生变化。示例:BigDecimal.valueOf(toBeTruncated).setScale(3,RoundingMode.HALF_UP)的输出为12.500

then after .doubleValue(), the output will be 12.5 i.e. precision is lost.

然后在.doubleValue()之后,输出将为12.5,即精度丢失。

Solution either use BigDecimal type without .doubleValue() method to display or use string formatting after the final answer

解决方案要么使用BigDecimal类型而不使用.doubleValue()方法,要么在最终答案后显示或使用字符串格式

#11


-1  

Maybe this method would help you for precising double values.

也许这种方法可以帮助你精确化双重值。

double truncate(double number)
    {
        int integerPart = (int) number;
        double fractionalPart = number - integerPart;
        fractionalPart *= 100;  //It is for upto two decimal values after point.
                                //You can increase the zeros to fulfill your needs.
        int fractPart = (int) fractionalPart;
        fractionalPart = (double) (integerPart) + (double) (fractPart)/100;
        return fractionalPart;
    }

This method will allow to set the precision level.

此方法将允许设置精度级别。

double truncate(double number, int precision)
{
    double prec = Math.pow(10, precision);
    int integerPart = (int) number;
    double fractionalPart = number - integerPart;
    fractionalPart *= prec;
    int fractPart = (int) fractionalPart;
    fractionalPart = (double) (integerPart) + (double) (fractPart)/prec;
    return fractionalPart;
}

#12


-1  

public static String setPrecision(String number, int decimal) {
    double nbr = Double.valueOf(number);
    int integer_Part = (int) nbr;
    double float_Part = nbr - integer_Part;
    int floating_point = (int) (Math.pow(10, decimal) * float_Part);
    String final_nbr = String.valueOf(integer_Part) + "." + String.valueOf(floating_point);
    return final_nbr;
}