我需要在Java中进行一些浮点运算,如下面的代码所示:
public class TestMain {
private static Map<Integer, Double> ccc = new HashMap<Integer, Double>() {
{ put(1, 0.01); put(2, 0.02); put(3, 0.05); put(4, 0.1); put(6, 0.2);
put(10, 0.5); put(20, 1.0); put(30, 2.0); put(50, 5.0); put(100, 10.0);
}
};
Double increment(Double i, boolean up) {
Double inc = null;
while (inc == null) {
inc = ccc.get(i.intValue());
if (up)
--i;
else
++i;
}
return inc;
}
public static void main(String[] args) {
TestMain tt = new TestMain();
for (double i = 1; i < 1000; i += tt.increment(i, true)) {
System.out.print(i + ",");
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是为了模拟Betfair微调器小部件作为输出给出的值的范围.
Java中的浮点运算似乎会引入一些意外错误.例如,我得到2.180000000000001而不是2.18.浮点数的用途是什么,你不能相信对它们执行的算术结果?我该如何解决这个问题?
Jon*_*eet 33
如果您需要精确的十进制值,则应使用java.math.BigDecimal
.然后阅读"每个计算机科学家应该知道什么关于浮点运算"的背景知识为什么你得到这些结果.
(我有一篇以.NET为中心的文章,你可能会发现它更容易阅读 - 当然也更短.为了理解这个问题,Java和.NET之间的差异大多不相关.)
Jay*_*Jay 11
浮点数使用二进制分数而不是小数分数.也就是说,你习惯于由十分位数,百分位数,千分位数等组成的小数分数.d1/10 + d2/100 + d3/1000 ......但是浮点数是二进制的,所以他们有半位数,四分之一位数,第八位数等.d1/2 + d2/4 + d3/8 ......
许多小数部分不能精确地表示为任何有限数量的二进制数字.例如,1/2是没有问题的:在十进制中它是.5,在二进制中它是.1.3/4是十进制.75,二进制.11.但是1/10是一个干净的.1(十进制),但是二进制它是.0001100110011 ......"0011"永远重复.由于计算机只能存储有限数量的数字,因此必须将其切断,因此答案并不准确.当我们在输出时转换回十进制时,我们得到一个奇怪的数字.
正如Jon Skeet所说,如果你需要精确的小数,请使用BigDecimal.如果性能是一个问题,您可以滚动自己的小数部分.就像,如果你知道你总是想要3个小数位并且数字不会超过一百万左右,你可以简单地使用带有假设3位小数的int,在你算术和写输出时根据需要进行调整format函数在正确的位置插入小数点.但99%的时间表现不是一个值得麻烦的大问题.