【问题标题】:How do I round a double to two decimal places in Java? [duplicate]如何在 Java 中将双精度位舍入到小数点后两位? [复制]
【发布时间】:2011-08-08 07:10:17
【问题描述】:

这是我将双精度数舍入到小数点后 2 位的操作:

amount = roundTwoDecimals(amount);

public double roundTwoDecimals(double d) {
    DecimalFormat twoDForm = new DecimalFormat("#.##");
    return Double.valueOf(twoDForm.format(d));
}

如果金额 = 25.3569 或类似的值,这很有效,但如果金额 = 25.00 或金额 = 25.0,那么我得到 25.0!我想要的是四舍五入以及格式化为 2 位小数。

【问题讨论】:

  • 这个函数有时会返回 ,而不是 。在 android 上,因此 Double.valueOf() 抛出异常

标签: java double


【解决方案1】:

你可以使用这个功能。

import org.apache.commons.lang.StringUtils;
public static double roundToDecimals(double number, int c)
{
    String rightPad = StringUtils.rightPad("1", c+1, "0");
    int decimalPoint = Integer.parseInt(rightPad);
    number = Math.round(number * decimalPoint);
    return number/decimalPoint;
}

【讨论】:

    【解决方案2】:

    首先声明一个DecimalFormat类的对象。注意DecimalFormat 中的参数是#.00,这意味着四舍五入的小数点后两位。

    private static DecimalFormat df2 = new DecimalFormat("#.00");
    

    现在,将格式应用于您的双精度值:

    double input = 32.123456;
    System.out.println("double : " + df2.format(input)); // Output: 32.12
    

    注意double input = 32.1;的情况

    那么输出将是32.10 等等。

    【讨论】:

      【解决方案3】:

      你在用钱工作吗?创建一个String 然后再将其转换回来是非常循环的。

      使用BigDecimal。这已经被相当广泛地讨论过了。你应该有一个Money 类,并且数量应该是一个BigDecimal

      即使您不花钱,也可以考虑BigDecimal

      【讨论】:

      • 是的。我在做钱。但我所做的只是小费 =(金额 * 百分比)/100 并显示小费和金额。我已经考虑过 BigDecimal,但对于这种简单的计算来说似乎经历了很多痛苦。在这种情况下,是不是有一个单独的货币类别太过分了?
      • 地狱没有。 OO 编程意味着类是打字问题的答案。问自己一个问题:Money 是一类对象吗?显然答案是肯定的。如果这个论点没有影响你,这里还有 2 个:1.来自分析模式的 Martin Fowler 论点:需要对单位进行建模或坏事发生,以及 2.如果你愿意,我可以给你一个理财课程。
      • 我不是 OOP 的专业人士,但你们能告诉我金钱类应该包含什么或如何处理该主题的情况。我真的可以弄清楚。
      • 建议某人更改数据类型作为解决方案可能不适用于大多数工作开发人员。
      • Rob 做了很多推论。对否决者问题的精彩分析!对OP问题的分析怎么样? “我想,如果你唯一的工具是一把锤子,那么把所有东西都当成钉子一样对待是很诱人的。” _马斯洛
      【解决方案4】:
          int i = 180;
          int j = 1;
          double div=  ((double)(j*100)/i);
          DecimalFormat df = new DecimalFormat("#.00"); // simple way to format till any deciaml points
          System.out.println(div);
          System.out.println(df.format(div));
      

      【讨论】:

        【解决方案5】:

        这是一种保证输出四舍五入到小数点后两位的myFixedNumber的简单方法:

        import java.text.DecimalFormat;
        
        public class TwoDecimalPlaces {
            static double myFixedNumber = 98765.4321;
            public static void main(String[] args) {
        
                System.out.println(new DecimalFormat("0.00").format(myFixedNumber));
            }
        }
        

        结果是:98765.43

        【讨论】:

          【解决方案6】:
          DecimalFormat df = new DecimalFormat("###.##");
          double total = Double.valueOf(val);
          

          【讨论】:

          • 一旦你达到 999 以上的数字,此解决方案与原始代码存在相同的问题。
          【解决方案7】:

          你可以试试这个:

          public static String getRoundedValue(Double value, String format) {
              DecimalFormat df;
              if(format == null)
                  df = new DecimalFormat("#.00");
              else 
                  df = new DecimalFormat(format);
              return df.format(value);
          }
          

          public static double roundDoubleValue(double value, int places) {
              if (places < 0) throw new IllegalArgumentException();
          
              long factor = (long) Math.pow(10, places);
              value = value * factor;
              long tmp = Math.round(value);
              return (double) tmp / factor;
          }
          

          【讨论】:

            【解决方案8】:

            其中 num 是双精度数

            • 整数 2 表示我们要打印的小数位数。
            • 这里我们取小数点后 2 位

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

            【讨论】:

              【解决方案9】:

              您可以使用 Apache Commons Math:

              Precision.round(double x, int scale)
              

              来源:http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html#round(double,%20int)

              【讨论】:

                【解决方案10】:

                从 java 1.8 开始,您可以使用 lambda 表达式做更多事情并检查 null。此外,下面的一个可以处理浮点数或双精度数和可变数量的小数点(包括 2 :-))。

                public static Double round(Number src, int decimalPlaces) {
                
                    return Optional.ofNullable(src)
                            .map(Number::doubleValue)
                            .map(BigDecimal::new)
                            .map(dbl -> dbl.setScale(decimalPlaces, BigDecimal.ROUND_HALF_UP))
                            .map(BigDecimal::doubleValue)
                            .orElse(null);
                }
                

                【讨论】:

                  【解决方案11】:

                  使用这个

                  String.format("%.2f", doubleValue) // 根据您的要求更改 2。

                  【讨论】:

                  • 哥们,你真是个天才!我一直试图让它工作一段时间。你的评论就是这样。 lblTotal.setText(String.format("$%.2f",tip));
                  【解决方案12】:

                  双倍金额 = 25.00;

                  NumberFormat 格式化程序 = new DecimalFormat("#0.00");

                  System.out.println(formatter.format(amount));

                  【讨论】:

                  • 你需要解释为什么这段代码能解决问题,为什么这是最好的解决方案等等。
                  【解决方案13】:

                  假设金额可以是正数也可以是负数,四舍五入到小数点后两位可以使用以下代码sn-p。

                  amount = roundTwoDecimals(amount);
                  
                  public double roundTwoDecimals(double d) {
                      if (d < 0)
                         d -= 0.005;
                      else if (d > 0)
                         d += 0.005;
                      return (double)((long)(d * 100.0))/100);
                  }
                  

                  【讨论】:

                    【解决方案14】:

                    Math.round 是一个答案,

                    public class Util {
                     public static Double formatDouble(Double valueToFormat) {
                        long rounded = Math.round(valueToFormat*100);
                        return rounded/100.0;
                     }
                    }
                    

                    在 Spock、Groovy 中测试

                    void "test double format"(){
                        given:
                             Double performance = 0.6666666666666666
                        when:
                            Double formattedPerformance = Util.formatDouble(performance)
                            println "######################## formatted ######################### => ${formattedPerformance}"
                        then:
                            0.67 == formattedPerformance
                    
                    }
                    

                    【讨论】:

                    • valueToFormat = 0d 返回 0.0,而不是 0.00。即使在小数点为 0 的情况下,原始问题也询问了两位小数。
                    【解决方案15】:

                    这是我能做到的最简单的方法,但它比我见过的大多数示例更容易完成工作。

                        double total = 1.4563;
                    
                        total = Math.round(total * 100);
                    
                        System.out.println(total / 100);
                    

                    结果是 1.46。

                    【讨论】:

                      【解决方案16】:

                      您可以使用 apache common 中的 org.apache.commons.math.util.MathUtils

                      double round = MathUtils.round(double1, 2, BigDecimal.ROUND_HALF_DOWN);

                      【讨论】:

                        【解决方案17】:

                        只需使用:(简单易行)

                        double number = 651.5176515121351;
                        
                        number = Math.round(number * 100);
                        number = number/100;
                        

                        输出将是 651.52

                        【讨论】:

                        • 他将数字乘以 100(因此 651.517 变为 65151.7...)并将其四舍五入到最接近的 1(因此变为 65152),然后再除以 100(651.52)。跨度>
                        • 你应该写100.0而不是100,否则它会把它当作int。
                        • @Anatoly 否 - Java 从左到右计算并扩展到所有操作数的最佳匹配。 number 是双精度数,因此所有使用 number 计算的参与者都会扩展为双精度数!
                        • Math.round(0 * 100) / 100 ==> 输出为 0,而不是 0.00
                        • Math.round(num * 100) / 100.00
                        【解决方案18】:

                        您的 Money 类可以表示为 Long 的子类,或者具有一个将货币值表示为本地 long 的成员。然后,在为您的货币实例分配值时,您将始终存储实际上是真实货币值的值。您只需使用适当的格式输出您的 Money 对象(通过您的 Money 覆盖的 toString() 方法)。例如,Money 对象的内部表示中的 1.25 美元是 125。您将钱表示为美分、便士或任何您要密封的货币的最小面额是……然后在输出时对其进行格式化。不,您永远不能存储“非法”货币价值,例如 1.257 美元。

                        【讨论】:

                          【解决方案19】:

                          如果您希望结果保留两位小数,您可以这样做

                          // assuming you want to round to Infinity.
                          double tip = (long) (amount * percent + 0.5) / 100.0; 
                          

                          此结果不精确,但 Double.toString(double) 将对此进行更正并打印一到两位小数。但是,一旦您执行另一次计算,您就可以得到一个不会被隐式四舍五入的结果。 ;)

                          【讨论】:

                            【解决方案20】:

                            不能“将双精度数舍入到 [任意数量] 小数位”,因为双精度数没有小数位。您可以将 double 转换为带有 N 个小数位的 base-10 字符串,因为 base-10 确实有小数位,但是当您将其转换回来时,您又回到了 double-land,带有 binary 小数位.

                            【讨论】:

                            • 我知道。对不起,我没有正确表达自己。
                            • @sherry 你表达得很好,你只是描述了一个不可能的要求。
                            • 投反对票。我觉得作者的意图很明显。如果像其他答案一样,它有类似“但是,你可以 ...”之类的内容,那就没问题了。
                            • @ChristopherSchneider 以“you can ...”开头的句子完全符合您的反对意见。
                            【解决方案21】:

                            使用数字占位符 (0),与“#”一样,尾随/前导零显示为不存在:

                            DecimalFormat twoDForm = new DecimalFormat("#.00");
                            

                            【讨论】:

                            • 好吧..那没用。我仍然得到 25.0。
                            • 我使用字符串格式化来解决这个问题,String result = String.format("%.2f", amount);
                            • 投反对票的请发表评论。
                            猜你喜欢
                            • 1970-01-01
                            • 1970-01-01
                            • 2010-11-29
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            相关资源
                            最近更新 更多