dan*_*enz 0 java floating-point floating-accuracy floating-point-conversion
我最近对Java很近.我一般都了解浮点精度和转换的问题,但不确定为什么在Java中看到如此荒谬的结果......我这样做了......
String str1 = String.format("%.02f", 0.001921921f);
String str2 = String.format("%.02f", 9.0921921f);
String str3 = String.format("%.02f", 91.21921f);
String str4 = String.format("%.02f", 911212.09f); // WIERD: Prints 911212.06 !!!
String str5 = String.format("%.02f", 1212f);
Run Code Online (Sandbox Code Playgroud)
并在调试模式下看到字符串中的这些值(Eclipse调试器/ Eclipse平台4.2.1/Java SE 6(Mac Mavericks OSX默认))...
str1 = "0.00"
str2 = "9.09"
str3 = "91.22"
str4 = "911212.06" ===> What the heck ?? Should be "911212.09" or some rounding of that?
str5 = "1212.00"
Run Code Online (Sandbox Code Playgroud)
我根本不明白这一点.
Lemme还解释了我最终要做的事情......
我有一堆输入浮点值到不同的小数精度,从"9.34","99.131"等字符串转换而来.
我想截断超过秒的所有小数位并得到一个带有所有数字的INT(没有小数位,没有楼/天花板/舍入等)即ie.19.2341将成为1923年,19.2359也将成为1923年而不是1924年.
现在我尝试做类似的事情
int ival = (int)(float_val * 100.0);
Run Code Online (Sandbox Code Playgroud)
但这有精确/准确性问题.例如.如果float_val包含17.3f,则ival变为1729.
我认为使用格式化的字符串可能会有所帮助,但这也会进行舍入,并且在尝试时我也看到了上面的奇怪案例.
知道我做错了什么吗?
现在,对于我的情况,我只是操纵原始字符串值来截断小数位并删除小数点然后转换为int.
A float具有23位精度.要表示911212.09,在+或 - 0.005的范围内,需要27位(我可以关闭一个).因此,结果不应该是令人惊讶的.
如果您使用double(通过f从数字文字中删除),您将获得52位精度,因此错误足够小,以至于当您格式化为两位小数时它不会影响结果.
但使用BigDecimal更好.
顺便说一下,这不是Java或JDK问题.它将出现在您尝试使用32位IEEE 754浮点类型的任何语言中.请阅读每个计算机科学家应该知道的关于浮点运算的内容.
您的问题很简单,即float(如IEEE 754格式所述)的实习生表示不够精确,无法911212.09f按预期处理.
它实际上只存储在32位值上,分布如下:
这留给我们的只有23位精度,我们可以表示为最接近float于911212.09实际是911212.0625.
通过阅读本维基百科条目或使用此在线转换器,您可以更深入地了解这一切是如何工作的:IEEE 754转换器

正如@ajb在他的回答中提到的那样,只需使用该double类型就可以让你对这种情况进行排序;)
即:
// removed 'f' here
// v
System.out.println(String.format("%.02f", 911212.09));
Run Code Online (Sandbox Code Playgroud)
...将输出:
911212.09
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
493 次 |
| 最近记录: |