如何显示浮点数的附加数字?

发布于 2025-01-03 05:47:44 字数 327 浏览 3 评论 0原文

我有一个像这样创建的 Double

Double d = Double.parseDouble( "27.86753" ); // All the digits of this double value are 27.867530822753906

这个特殊的双精度数也可以用浮点数表示,因此 Java 会丢弃其余的数字。如何强制 Java 给出该值的真正双精度表示形式(所有数字)?

I have a Double which I created like this:

Double d = Double.parseDouble( "27.86753" ); // All the digits of this double value are 27.867530822753906

This particular double can also be represented by a float, so Java drops the rest of my digits. How can I force Java to give me the true double representation (all of the digits) of this value?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一张白纸 2025-01-10 05:47:44

哦,伙计,有趣。您想确切地了解 double 如何不准确地执行此操作。

我认为 new BigDecimal(double).toString() 会给您所有不正确的结果数字,因为 BigDecimal 表示具有精确指定精度的数字。

编辑:哦哦哦哦,我想我明白发生了什么事。

让我尝试这样解释它: Double.toString 返回最不精确的 String,这样 Double.parseDouble 将返回完全相同的 >double -- 刚好足够的数字来“唯一标识”确切的 IEEE 754 值,尽管实际值可能比打印的数字更多。仅仅因为 Double.toString 没有提供您期望的位数并不意味着实际 IEEE 754 双精度值会四舍五入到那么多位数。 new BigDecimal(double).toString 将返回所存储的准确 IEEE-754 值。

更新:

发生的事情是,当它打印出27.86753时,它实际上是一个比您引用为正确答案的数字27.867530822753906更精确的值。这是因为 toString 被设计为仅打印必要的内容,以确保 Double.parseDouble(Double.toString(value)) 是无操作。

我运行了以下代码:

public static void main(String[] args) {
  double dWithFloat = Double.parseDouble(Double.toString(Float.parseFloat("27.86753")));
  double dJustParsed = Double.parseDouble("27.86753");
  System.out.println(dWithFloat);
  System.out.println(dJustParsed);

  BigDecimal bigFromFloat = new BigDecimal(dWithFloat);
  BigDecimal bigJustParsed = new BigDecimal(dJustParsed);
  System.out.println(bigFromFloat); 
    // prints the exact value from the double,
    // doesn't round or truncate like Double.toString
  System.out.println(bigJustParsed);

}

并打印出来

27.867530822753906 // Double.toString(Double.parseDouble(Double.toString(Float.parseFloat("27.86753"))));
27.86753 // Double.toString(Double.parseDouble("27.86753")) is indeed a no-op
27.86753082275390625 // This is the _actual_ value from D.parseD(D.toString(F.parseF("27.86753")))
27.867529999999998580051396857015788555145263671875 // This is the actual value from D.parseD("27.86753")

事实上,第二个值明显更接近 27.86753,差距约为 0.0000008。

Oh, man, interesting. You want to learn exactly how double does it inaccurately.

I think new BigDecimal(double).toString() will give you all of the incorrect digits, since BigDecimal represents a number with a precisely specified precision.

EDIT: Ohhhhhhhh, I think I see what's going on.

Let me try to explain it like this: Double.toString returns the least precise String such that Double.parseDouble will return exactly the same double -- just enough digits to "uniquely identify" the exact IEEE 754 value, though the actual value may have more digits than are printed. Just because Double.toString isn't giving you as many digits as you expect doesn't mean that the actual IEEE 754 double-precision value is being rounded to that many digits. new BigDecimal(double).toString will return the exact IEEE-754 value being stored.

UPDATE:

What's going on is that when it prints out 27.86753, it's actually internally a more precise value than the digits you're quoting as the correct answer, 27.867530822753906. That's just because toString is designed to print out only as much as necessary to ensure that Double.parseDouble(Double.toString(value)) is a no-op.

I ran the following code:

public static void main(String[] args) {
  double dWithFloat = Double.parseDouble(Double.toString(Float.parseFloat("27.86753")));
  double dJustParsed = Double.parseDouble("27.86753");
  System.out.println(dWithFloat);
  System.out.println(dJustParsed);

  BigDecimal bigFromFloat = new BigDecimal(dWithFloat);
  BigDecimal bigJustParsed = new BigDecimal(dJustParsed);
  System.out.println(bigFromFloat); 
    // prints the exact value from the double,
    // doesn't round or truncate like Double.toString
  System.out.println(bigJustParsed);

}

and it printed out

27.867530822753906 // Double.toString(Double.parseDouble(Double.toString(Float.parseFloat("27.86753"))));
27.86753 // Double.toString(Double.parseDouble("27.86753")) is indeed a no-op
27.86753082275390625 // This is the _actual_ value from D.parseD(D.toString(F.parseF("27.86753")))
27.867529999999998580051396857015788555145263671875 // This is the actual value from D.parseD("27.86753")

And indeed, this second value is noticeably closer to 27.86753, by a margin of something like 0.0000008.

西瓜 2025-01-10 05:47:44

您可能需要考虑使用 java.math.BigDecimal ,您可以通过明确的方法来控制比例和舍入规则。你不能用 Double 做到这一点。

You might want to consider using java.math.BigDecimal where you have explicit ways to control scale and rounding rules. You cannot do it with Double.

机场等船 2025-01-10 05:47:44

丑陋但有效:

Double d = Double.parseDouble( Double.toString( Float.parseFloat( "27.86753" ) ) ); // Sets the value of the Double to 27.867530822753906

Ugly but it works:

Double d = Double.parseDouble( Double.toString( Float.parseFloat( "27.86753" ) ) ); // Sets the value of the Double to 27.867530822753906
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文