【问题标题】:Java: How to set Precision for double value? [duplicate]Java:如何为双精度值设置精度? [复制]
【发布时间】:2013-01-28 13:11:27
【问题描述】:

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

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

10.0000

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

有没有更好的办法,像下面这样说:

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

【问题讨论】:

标签: java


【解决方案1】:

你可以试试BigDecimal这个目的

Double toBeTruncated = new Double("3.5789055");

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

【讨论】:

  • 为什么没有人对这个答案投赞成票,这是完美的。
  • 效果不错,“new Double”可以去掉
  • 调用doubleValue()时会不会有有损转换?
  • 尝试 double r1 = BigDecimal.valueOf(2.945777946674339E8D).setScale(3, RoundingMode.HALF_UP).doubleValue();--- 你得到 2.94577794667E8。输出看起来与您的要求不同。
  • @veritas 它在特定情况下有效,因为 0.5 具有精确的 FP 表示。大多数分数都没有。
【解决方案2】:

您不能将双精度(或双精度)设置为指定的小数位数,因为浮点值没有小数位数。它们有二进制数字。

您必须通过BigDecimalDecimalFormat 转换为十进制基数,具体取决于您以后要对该值做什么。

另请参阅我对 this question 的回答,以驳斥不可避免的 *100/100 答案。

【讨论】:

    【解决方案3】:

    这是一个简单的方法:

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

    它将精度设置为 2 位。

    如果你只想打印,这样使用:

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

    【讨论】:

    • 澄清一下:double myDouble = 42.99; String formatted = String.format("%.2f", myDouble);
    • 这不会将精度设置为 2 位。它将一个数字四舍五入到 2 位精度。那不是一回事。如果由于精度不足而首先四舍五入的数字包含错误的值,则四舍五入将无济于事。
    • @Gili,你能解释一下精度和舍入之间的区别吗?一些例子会更有帮助
    • @Vipresh Per stackoverflow.com/a/14845954/14731 double 包含一个固定的精度。如果您将0.1 相加十次,您将得到一个不严格等于1.0 的双精度数。这是因为浮点数不能准确地表示所有十进制数,即使是具有(十进制)精度的一位数。如果您在一个已经不精确的数字上调用 String.format(),则无法保证结果将精确到 2 位精度。
    【解决方案4】:

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

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

    所以它会打印小数点后两位数,它会打印 12.79

    【讨论】:

    • OP 已经拒绝了这个解决方案,天知道为什么。
    • @EJP 为什么?!!
    • @AndreasL。我已经表达了我的困惑。我没有什么要补充的。您的问题应该向 OP 提出,而不是向我提出。
    • 如果你想要一定的精度,你不应该添加额外的创建字符串的步骤(通过格式化)。更好的解决方案是仅对 Double 值进行操作。精度不仅仅是表示的问题。
    【解决方案5】:

    这对我有用:

    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】:

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

      1. 将精度限制为“最大”N 位(不固定为 N 位)。
      2. 将数字向下舍入(不四舍五入)。

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

      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
      

      这是代码。我上面提到的两个警告可以很容易地解决,但是,速度对我来说比准确性更重要,所以我把它留在这里。 与数学运算相比,System.out.printf("%.2f",123.234); 等字符串操作的计算成本很高。在我的测试中,与字符串操作相比,以下代码(没有 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;
      }
      

      【讨论】:

        【解决方案7】:

        doublefloat 的精度取决于它们的大小和IEEE floating point types 的实现方式。

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

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

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

        【讨论】:

          【解决方案8】:
          BigDecimal value = new BigDecimal(10.0000);
          value.setScale(4);
          

          【讨论】:

          • Rounding necessary 使用10.01时引发异常!
          【解决方案9】:

          为了扩展@EJP,处理双打时的“精度”概念非常令人担忧。正如https://stackoverflow.com/a/3730040/390153 中所讨论的,无论精度如何,您甚至都不能将 0.1 表示为双精度数,出于同样的原因,您不能以有限的精度表示以 10 为底的 1/3。

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

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

          b) 如果双精度是合适的,我所说的精度是什么意思?如果你只是在谈论显示,将逻辑包装在一个显示函数中,你只需要在一个地方处理它; IE。应用 DRY 原则。

          【讨论】:

            【解决方案10】:
            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;
            }
            

            【讨论】:

            • 简单的解决方案是使用 => Double.parseDouble(String.format("%.3f", d))
            【解决方案11】:

            也许这种方法可以帮助您精确计算双精度值。

            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;
                }
            

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

            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;
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-04-02
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多