【问题标题】:How to display the exact value as instantiated by the BigDecimal [duplicate]如何显示由 BigDecimal 实例化的确切值 [重复]
【发布时间】:2019-02-22 10:00:57
【问题描述】:

我想用这里实例化的确切值检索 bigDecimal 的值

BigDecimal balance = new BigDecimal(2300000870000000000067.7797);

我现在使用余额检索到的值是 2300000869999999975424。 您能否告知我如何将其检索为 2300000870000000000067.7797 本身?

【问题讨论】:

  • 您可以尝试使用toString() 获取确切的值,然后根据需要将其转换为数字。
  • 我认为 new BigDecimal("2300000870000000000067.7797");
  • 尝试使用字符串而不是 BigDecimal
  • @Maxouille 简直是错误和误导。当您不了解主题时提供建议有什么意义?
  • 重点是:当你使用基于字符串的构造函数时,无论如何你都会放弃精度。正如答案和 DUP 问题所暗示的那样:您绝对不想要双重构造函数。

标签: java


【解决方案1】:

你使用了java.math.BigDecimal.BigDecimal(double val)构造函数。

来自 JavaDoc

java.math.BigDecimal.BigDecimal(double val)


Translates a double into a BigDecimal which is the exact decimal representation of the double's binary floating-point value. The scale of the returned BigDecimal is the smallest value such that (10scale × val) is an integer. 

Notes: 
1. The results of this constructor can be somewhat unpredictable. One might assume that writing new BigDecimal(0.1) in Java creates a BigDecimal which is exactly equal to 0.1 (an unscaled value of 1, with a scale of 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the value that is being passed in to the constructor is not exactly equal to 0.1, appearances notwithstanding. 
2. The String constructor, on the other hand, is perfectly predictable: writing new BigDecimal("0.1") creates a BigDecimal which is exactly equal to 0.1, as one would expect. Therefore, it is generally recommended that the String constructor be used in preference to this one. 
3. When a double must be used as a source for a BigDecimal, note that this constructor provides an exact conversion; it does not give the same result as converting the double to a String using the Double.toString(double) method and then using the BigDecimal(String) constructor. To get that result, use the static valueOf(double) method. 

这里第一点表明:

这个构造函数的结果可能有点不可预测。 可以假设用 Java 编写 new BigDecimal(0.1) 会创建一个正好等于 0.1 的 BigDecimal(未缩放的值 1,带有1) 的比例,但实际上等于 0.1000000000000000055511151231257827021181583404541015625。这是因为 0.1 不能完全表示为双精度数(或者,就此而言,不能表示为任何有限长度的二进制分数)。因此,传递给构造函数的值并不完全等于 0.1,尽管看起来如此。

第二点建议使用带有字符串参数的构造函数来获取精确值。

这就是价值差异的原因。

【讨论】:

  • 主要效果似乎是将文字转换为双精度,而不是 BigDecimal 构造函数。
  • @JanLarsen 你的意思是使用这个构造函数的主要效果吧?
  • “这似乎是”最后一个短语应删除或更改为“这是”[:-)
  • @CarlosHeuberger 完成。谢谢。
  • @Raj 不,我的意思不是“使用这个构造器的主要效果”。我的意思是问题代码的主要影响。我试图在我的回答中解释它。
【解决方案2】:

您正在尝试使用不适合具有最大 15 位小数精度的双精度数的文字数字 - 这可能是您首先要使用 BigDecimal 的原因。因此,在初始化 BigDecimal 之前,您的数字将转换为双精度形式的最精确表示。然后 BigDecimal 构造器通过弄乱已经搞砸的双精度来加剧错误。

您必须将数字表示为字符串才能获得该精度。

    double x = 2300000870000000000067.7797d;
    System.out.println("double:"+x);        
    BigDecimal balance = new BigDecimal(2300000870000000000067.7797);
    System.out.println("balance:"+balance);
    BigDecimal stringbased = new BigDecimal("2300000870000000000067.7797");
    System.out.println("stringbased:"+stringbased);

打印

double:2.30000087E21
balance:2300000869999999975424
stringbased:2300000870000000000067.7797

【讨论】:

    【解决方案3】:

    java 文档本身建议BigDecimal(Double val)

    此构造函数的结果可能有些不可预测。

    您应该改用以下内容:

    BigDecimal balance = new BigDecimal("2300000870000000000067.7797");
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-07
      • 2013-06-27
      相关资源
      最近更新 更多