简体   繁体   English

在Java中使用parseFloat的正确方法是什么

[英]What's the right way to parseFloat in Java

I notice some issues with the Java float precision 我注意到Java浮点精度的一些问题

       Float.parseFloat("0.0065") - 0.001  // 0.0055000000134110451
       new Float("0.027") - 0.001          // 0.02600000000700354575
       Float.valueOf("0.074") - 0.001      // 0.07399999999999999999

I not only have a problem with Float but also with Double . 我不仅有Float的问题,还有Double

Can someone explain what is happening behind the scenes, and how can we get an accurate number? 有人可以解释幕后发生的事情,我们怎样才能获得准确的数字? What would be the right way to handle this when dealing with these issues? 在处理这些问题时,处理此问题的正确方法是什么?

The problem is simply that float has finite precision; 问题在于float具有有限的精度; it cannot represent 0.0065 exactly. 它不能完全代表0.0065 (The same is true of double , of course: it has greater precision, but still finite.) (当然, double也是如此:它具有更高的精度,但仍然是有限的。)

A further problem, which makes the above problem more obvious, is that 0.001 is a double rather than a float , so your float is getting promoted to a double to perform the subtraction, and of course at that point the system has no way to recover the missing precision that a double could have represented to begin with. 使上述问题更加明显的另一个问题是0.001是一个double而不是float ,所以你的float被提升为double来执行减法,当然在这一点上系统无法恢复double 可能代表的缺失精度。 To address that, you would write: 为了解决这个问题,你会写:

float f = Float.parseFloat("0.0065") - 0.001f;

using 0.001f instead of 0.001 . 使用0.001f而不是0.001

See What Every Computer Scientist Should Know About Floating-Point Arithmetic . 看看每个计算机科学家应该知道的关于浮点运算的内容 Your results look correct to me. 你的结果对我来说是正确的。

If you don't like how floating-point numbers work, try something like BigDecimal instead. 如果您不喜欢浮点数的工作方式,请尝试使用类似BigDecimal的方法

You're getting the right results. 你得到了正确的结果。 There is no such float as 0.027 exactly, nor is there such a double . 没有像0.027那样的float ,也没有这样的double You will always get these errors if you use float or double . 如果使用floatdouble总会出现这些错误。

float and double are stored as binary fractions : something like 1/2 + 1/4 + 1/16... You can't get all decimal values to be stored exactly as finite-precision binary fractions. floatdouble存储为二进制分数 :类似于1/2 + 1/4 + 1/16 ......您无法将所有十进制值精确地存储为有限精度二进制分数。 It's just not mathematically possible. 这在数学上是不可能的。

The only alternative is to use BigDecimal , which you can use to get exact decimal values. 唯一的选择是使用BigDecimal ,您可以使用它来获取精确的十进制值。

From the Java Tutorials page on Primitive Data Types : 从“ 原始数据类型Java教程”页面

A floating-point literal is of type float if it ends with the letter F or f ; 如果浮点字面值以字母Ff结尾,则浮点字面值为float类型; otherwise its type is double and it can optionally end with the letter D or d . 否则它的类型是双倍的,它可以选择以字母Dd结尾。

So I think your literals ( 0.001 ) are doubles and you're subtracting doubles from floats. 所以我认为你的文字( 0.001 )是双打的,你从浮动中减去双打。

Try this instead: 试试这个:

System.out.println((0.0065F - 0.001D)); // 0.005500000134110451
System.out.println((0.0065F - 0.001F)); // 0.0055

... and you'll get: ......你会得到:

0.005500000134110451
0.0055

So add F suffixes to your literals and you should get better results: 因此,在文字中添加F后缀,您应该得到更好的结果:

Float.parseFloat("0.0065") - 0.001F
new Float("0.027") - 0.001F
Float.valueOf("0.074") - 0.001F

I would convert your float to a string and then use BigDecimal. 我会将你的浮点数转换为字符串,然后使用BigDecimal。

This link explains it well 这个链接解释得很好

new BigDecimal(String.valueOf(yourDoubleValue));

Dont use the BigDecimal double constructor though as you will still get errors 不要使用BigDecimal双构造函数,因为你仍然会得到错误

Long story short if you require arbitrary precision use BigDecimal not float or double. 如果您需要任意精度,请使用BigDecimal,不要浮动或加倍。 You will see all sorts of rounding issues of this nature using float. 你会看到使用float这种性质的各种舍入问题。

As an aside be very careful not to use the float/double constructor of BigDecimal because it will have the same issue. 另外要小心不要使用BigDecimal的float / double构造函数,因为它会有同样的问题。 Use the String constructor instead. 请改用String构造函数。

Floating point cannot accurately represent decimal numbers. 浮点不能准确表示十进制数。 If you need an accurate representation of a number in Java, you should use the java.math.BigDecimal class: 如果您需要在Java中准确表示数字,则应使用java.math.BigDecimal类:

BigDecimal d = new BigDecimal("0.0065");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将SQLite与我的Java EE应用程序集成的正确方法是什么? - What's the right way to integrate SQLite with my Java EE app? 用Java产生XML内容的正确方法是什么? - What's the right way to produce a XML content in Java? 在Couchbase Java SDK中使用toBlocking()的正确方法是什么? - What's the right way to use toBlocking() in Couchbase Java SDK? Java 8 中评估 /path/a 是否是 /path 的子目录的正确方法是什么? - What's the right way in Java 8 to evaluate if /path/a is a subdirectory of /path? 解决 Codility 的 PermMissingElem 测试的正确方法是什么? (爪哇) - What is the right way to solve Codility's PermMissingElem test? (Java) Java:编写通用HashMap合并方法的正确方法是什么? - Java: What's the right way of writing a generic HashMap merge method? Java 中连接 Microsoft Access 2007 数据库的正确方法是什么? - What's the right way in Java to connect to a Microsoft Access 2007 database? 表示电话号码的正确方法是什么? - What's the right way to represent phone numbers? 在Java中处理NaN的正确方法是什么? - What is the right way to handle NaN in Java? 将私有Java9模块的程序包公开给JUnit的正确方法是什么? - What is the right way to expose a private Java9 module's package to JUnit?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM