舍入错误?

在我的课程中,我被告知:

连续值大概在内存中表示,因此使用浮点计算涉及舍入错误。 这些是位模式的微小差异; 因此如果ef是浮动的,testinge==f是不安全的。

引用Java。

这是真的? 我用double s和float s来比较语句,并且从来没有舍入的问题。 我从来没有读过类似的教科书。 虚拟机肯定是这个原因吗?

这是真的。

这是浮点值在内存中以有限的位数表示的固有限制。

这个程序,例如,打印“假”:

 public class Main { public static void main(String[] args) { double a = 0.7; double b = 0.9; double x = a + 0.1; double y = b - 0.1; System.out.println(x == y); } } 

你不用精确地比较'==',而是通常在一定程度上决定精确度,并询问数字是否“足够接近”:

 System.out.println(Math.abs(x - y) < 0.0001); 

对于Java而言,这同样适用于任何使用浮点的其他语言。 这是硬件中浮点值表示的固有devise。

有关浮点值的更多信息:

计算机科学家应该知道什么是浮点运算

是的,在基数2中恰好代表0.1,与在10代中完全代表1/3相同。

这总是如此。 有些数字不能用浮点数表示准确表示。 考虑一下,例如,pi。 你如何在一个有限的存储空间中表示一个无限数字的数字? 因此,在比较数字时,您应该检查它们之间的差异是否小于某个小数。 此外,还有几个类可以帮助您实现更高的精度,如BigDecimal和BigInteger。

这是正确的。 请注意,Java与它无关,这个问题在ANY语言中是浮点math所固有的。

你经常可以逃避教室级别的问题,但是在现实世界中是不行的。 有时在课堂上不行。

很久以前回到学校的事件。 一个介绍课的老师指定了一个期末考试的问题,这对许多优秀的学生来说是一个真正的愚蠢 – 这不是工作,他们不知道为什么。 (我把这个作为实验助手,我不在课堂上)最后一些人开始向我求助,一些探测揭示了这个问题:他们从来没有被教过关于浮点math固有的不准确性。

现在,这个问题有两个基本的解决方法,一个是暴力破解(在这种情况下偶然的工作,因为它每次都犯同样的错误),另一个是更优雅的(这会造成不同的错误,不起作用)。为什么试着用优雅的方法打砖墙呢? 我帮了他们一大堆,并解释了为什么,如果他有问题与我联系。

当然下个学期我从他那里听到这个消息,我基本上用一个简单的小程序把整个部门弄好了:

 10 X = 3000000 20 X = X + 1 30 If X < X + 1 goto 20 40 Print "X = X + 1" 

尽pipe部门的每位老师都认为,这终止。 300万种子只是为了使其终止更快。 (如果你不懂基本的话:这里没有噱头,只是耗尽了浮点数的精度。)

是的,正如其他答案所说。 我想补充一点,我build议你这篇关于浮点精度的文章: 可视化浮点数

是的,Java也使用浮点运算。

当然这是事实。 想想看。 任何数字都必须用二进制表示。

图片:“1000”为0.5或1/2,即2 ** -1。 那么“0100”是0.25或1/4。 你可以看到我要去的地方

你能用这种方式代表多less个数字? 2 ** 4。 增加更多位复制可用空间,但它永远不会无限。 1/3或1/10,对于1 / n的事情,任何不是2的倍数的数字都不能真正表示。

1/3可以是“0101”(0.3125)或“0110”(0.375)。 如果你乘以3,就不会是1。当然,你可以添加特殊的规则。 说你“当你加了3次'0101',把它做成1”…这个方法从长远来看是行不通的。 你可以抓一些,但是那么1/6次2呢?

这不是一个二进制表示的问题,任何有限expression式都有你不能表示的数字,它们是无限的。

大多数CPU(和计算机语言)使用IEEE 754浮点运算。 使用这种表示法,有十进制数字,在这个表示法中没有确切的表示forms,例如0.1。 所以,如果你除以10,你将不会得到一个确切的结果。 当连续执行几个计算时,错误总结。 在python中试试下面的例子:

 >>> 0.1 0.10000000000000001 >>> 0.1 / 7 * 10 * 7 == 1 False 

这不是你所期望的math。

顺便说一句:关于浮点数的一个常见的误解是结果不准确,不能安全地互相配合。 只有你真的使用数字的小数部分,这才是真实的。 如果你所有的math都在整数域中,双精度和浮点精度与整数相同,也可以安全地进行比较。 例如,它们可以安全地用作循环计数器。