> x=seq(0,1,by=0.2)
> y=seq(0,1,by=0.2)
> y[4]
[1] 0.6
> x[3]
[1] 0.4
> 1-x[3]
[1] 0.6
> y[4]>1-x[3]
[1] TRUE

尼玛坑爹啊!

这样生成的y[4]好像有精度问题。如果用y[5]与x[2]就没问题。奇怪 [s:16]

<br />
x=seq(0,1,by=0.2)<br />
y=seq(0,1,by=0.2)</p>
<p>> y[4] == 0.6<br />
[1] FALSE<br />
> y[4]==1-x[3]<br />
[1] FALSE<br />
> y[4]-(1-x[3])<br />
[1] 1.110223e-16</p>
<p>#但是<br />
> y[5]==(1-x[2])<br />
[1] TRUE<br />
> y[5]>(1-x[2])<br />
[1] FALSE<br />
> y[5]-(1-x[2])<br />
[1] 0<br />
</p>

http://cos.name/cn/topic/106109

佛曰:

0.6==0.6
</p>

只是你没有看透,此0.6只是梦幻泡影

<br />
options(digits = 22)<br />
x = seq(0, 1, by = 0.2)<br />
y = seq(0, 1, by = 0.2)<br />
y[4]<br />
# [1] 0.6000000000000000888178<br />
x[3]<br />
# [1] 0.4000000000000000222045<br />
1 - x[3]<br />
# [1] 0.5999999999999999777955<br />
y[4] > 1 - x[3]<br />
# [1] TRUE<br />
y[4] - (1 - x[3]) > 1e-9<br />
# [1] FALSE<br />
</p>

难道是seq的数值生成机制有问题?抑或力不能及?

或曰,浮点数慎用比较,早用阈值早超生 。。。

回复 第3楼 的 nan.xiao:

一个options(digits = 22),破尽万般幻法。

版主赞 [s:13]

安华版主这就该打板子了,作为R版版主,应该做到在凌晨四点突然被人叫醒问你10乘以0.1等于几,你在1秒钟之内斩钉截铁回答,不是1!(R FAQ 7.31)。

回复 第5楼 的 谢益辉:

<br />
> 10.0*.1==1.0<br />
[1] TRUE<br />
> which(1:10*.1==1:10/10)<br />
[1]  1  2  4  5  8  9 10<br />
> which(1/1:10*1:10==1)<br />
 [1]  1  2  3  4  5  6  7  8  9 10<br />
> which(1:10*.1==seq(.1,1,by=.1))<br />
[1]  1  2  3  4  5  7  8  9 10<br />
> which(1:10*.1==seq(0,1,length=11)[-1])<br />
 [1]  1  2  3  4  5  6  7  8  9 10<br />
</p>

回复 第6楼 的 RemembeR discoveR, invent:这只是夸张的说法而已,为了让楼主这样的疑惑更加刻骨铭心:)类似的例子还有很多,比如我本科的时候发现一个:

> .3-.7+.4<br />
[1] 5.551115e-17
</p>

回复 第5楼 的 谢益辉:

这倒冤枉jah了,我觉得是seq()函数的实现不够理想。直接算0.6 > 1 - 0.4 是会得到FALSE的,所以这个例子说明的是seq()的步长不一定等于你指定的那个浮点数。

回复 第7楼 的 谢益辉:Just on the contrary, my point is not 'when they are not equal', but 'when they are indeed equal even if the operands are not exactly represented in the float point system'.

回复 第9楼 的 RemembeR discoveR, invent:

When they come from the same mathematical path.

5 个月 后

不好意思来挖坟了。

在学Javascript: the definition guide 时看到下面一段:

The IEEE-754 floating-point representation used by JavaScript (and just about every

other modern programming language) is a binary representation, which can exactly

represent fractions like 1/2, 1/8, and 1/1024. Unfortunately, the fractions we use most

commonly (especially when performing financial calculations) are decimal fractions

1/10, 1/100, and so on. Binary floating-point representations cannot exactly represent

numbers as simple as 0.1.

JavaScript numbers have plenty of precision and can approximate 0.1 very closely. But

the fact that this number cannot be represented exactly can lead to problems. Consider

this code:

<br />
var x = .3 - .2; // thirty cents minus 20 cents<br />
var y = .2 - .1; // twenty cents minus 10 cents<br />
x == y // => false: the two values are not the same!<br />
x == .1 // => false: .3-.2 is not equal to .1<br />
y == .1 // => true: .2-.1 is equal to .1<br />
</p>

Because of rounding error, the difference between the approximations of .3 and .2 is

not exactly the same as the difference between the approximations of .2 and .1. It is

important to understand that this problem is not specific to JavaScript: it affects any

programming language that uses binary floating-point numbers.

当时也是震惊了,跑到R里看,发现也是一样的。

这个C语言等都是这样的。

不对浮点数进行比较,是程序员的常识。

4 个月 后

长姿势了。。浮点数之间慎用比较。。谨记谨记。