这个问题在这里已经有答案了:
浮点数学坏了吗((31个答案)
5年前关门了。
我需要用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 + ",");
}
}
}
这是为了模拟betfair微调器小部件输出的值的范围。
java中的浮点算法似乎会引入一些意想不到的错误。例如,我得到2.180000000000001而不是2.18。浮点数的用途是你不能相信对它们执行算术的结果?我怎样才能避开这个问题?
7条答案
按热度按时间omqzjyyz1#
顺便说一句,您可以尝试使用这个函数来确保(小数位数不要太多)您的数字将被重新格式化,只保留您需要的小数。
http://pastebin.com/cacer0xk
n
你的数字有很多小数吗。Math.PI
),numberOfDecimals
是所需的最大小数位数(例如,3.14为2或3.151为3)。从理论上讲,将
numberOfDecmals
,它也将截断数字的整数低位。e、 g推杆n=1588.22
以及numberOfDecimals=-2
,函数将返回1500.0
.如果有什么问题,请告诉我。
c86crjj02#
通过使用格式化输出,可以使程序的输出看起来更像您期望的那样。
http://java.sun.com/javase/6/docs/api/java/util/formatter.html
很明显,底层的浮点运算仍然是一样的,但至少输出的可读性会更好。
例如,要将结果四舍五入到小数点后两位:
nxagd54h3#
从哲学的Angular 来说,我想知道:今天大多数计算机cpu都内置了对整数运算和浮点运算的支持,但不支持十进制运算。为什么不?因为这个舍入问题,我已经有好几年没有写过浮动可用的应用程序了。你当然不能用它们来计算金额:没有人愿意在“42320003美元”的销售收据上打印价格。没有会计会接受“我们可能会在这里和那里的一分钱,因为我们使用二进制分数和舍入错误”。
浮子可以用来测量,比如距离或温度,在这里没有“精确答案”这样的东西,无论如何,你必须在某个点上四舍五入到你的仪器的精度。我想对于在化学实验室编写计算机程序的人来说,浮点数是经常使用的。但对我们这些商界人士来说,它们几乎毫无用处。
早在我在大型机上编程的古代,ibm360系列cpu就内置了对压缩十进制算法的支持。它们存储字符串,其中每个字节包含两个十进制数字,即前四位的值从0到9,后四位的值也是,cpu有算术函数来处理它们。为什么英特尔不能这样做?然后java可以添加一个“decimal”数据类型,我们就不需要所有额外的垃圾了。
当然,我不是说要废除浮动。只要加上小数。
哦,好吧,随着伟大的社会运动的进行,我不认为这是一个会产生很多民众的兴奋或街头骚乱。
7xzttuei4#
你可以在你的机器上写一些代码来计算epsilon。我相信std::c++定义了它,它的定义方式取决于您使用的是什么。
我唯一担心epsilon的时候是在比较阈值信号的时候。即使这样,我也不确定我是否真的需要担心它,根据我的经验,如果你关心epsilon,你可能需要先考虑其他一些问题。
ua4mk5z45#
浮点数使用二进制分数而不是十进制分数。也就是说,你已经习惯了由十分之一位、百分之一位、千分之一位等组成的小数,d1/10+d2/100+d3/1000。。。但是浮点数是二进制的,所以它们有半位数、四分之一位数、八分之一位数等等。。。
许多小数不能精确地用任何有限个二进制数字来表示。例如,1/2是没有问题的:十进制是.5,二进制是.1。3/4是十进制.75,二进制.11。但1/10在十进制中是干净的.1,但在二进制中是.000110011。。。“0011”永远在重复。由于计算机只能存储有限数量的数字,因此在某些情况下,这些数字必须被切掉,因此答案并不精确。当我们把输出转换回十进制时,我们得到一个奇怪的数字。
正如乔恩斯基特所说,如果你需要精确的小数点,使用bigdecimal。如果性能有问题,您可以自己滚动小数。比如,如果你知道你总是想要精确的3个小数位,并且数字不会超过一百万左右,你可以简单地使用int,假设3个小数位,在做算术时做必要的调整,并编写输出格式函数将小数点插入正确的位置。但是99%的时间性能不是一个值得麻烦的大问题。
6qqygrtg6#
如果需要精确的十进制值,应该使用
java.math.BigDecimal
. 然后阅读“每一位计算机科学家都应该知道的浮点运算”作为获得这些结果的背景。(我有一篇以.net为中心的文章,你可能会发现这篇文章更容易阅读,当然也更短。java和.net之间的差异对于理解这个问题基本上是无关的。)
dba5bblo7#
浮点数是不精确的,特别是因为它们是以二进制分数(1/2,1/4,1/8,1/16,1/32,…)而不是十进制分数(1/10,1/100,1/1000,…)工作的。只要定义你觉得“足够接近”的东西,然后使用
Math.abs(a-b) < 0.000001
.