cocos的向量比较方法里面直接用 === 比较x,y分量
proto.equals = function (other) {
return other && this.x === other.x && this.y === other.y;
};
浮点数不是有误差吗?请问这样比较没有问题吗?
代码地址:https://github.com/cocos-creator/engine/blob/master/cocos2d/core/value-types/CCVec2.js#L96
cocos的向量比较方法里面直接用 === 比较x,y分量
proto.equals = function (other) {
return other && this.x === other.x && this.y === other.y;
};
浮点数不是有误差吗?请问这样比较没有问题吗?
代码地址:https://github.com/cocos-creator/engine/blob/master/cocos2d/core/value-types/CCVec2.js#L96
你都知道有误差了,那这样比较当然有问题。
js是可以的,已经帮你计算过误差了

用区间比较啊. 大于等于 小于等于 .
浮点数计算在 JS 中确实有误差,但是这个误差是稳定的,也就是说相同的计算产生的误差是一样的。
比较的函数处理 equals 以外,我们还有一个 fuzzyEquals 可以传递可接受的误差 variance 参数
v1.fuzzyEquals(v2, 0.001);
只要不超过 variance 的范围,都当作 equal
虽然误差是稳定的,但是上面的例子里面,期望 (0.1,0.2)+(0.2,0.3)==(0.3,0.5),但equals的结果是false,那么equals的语义就没什么意义了,只能直接使用fuzzyEquals,那么还要equals有什么用呢,反而容易引起误用。
另外,cc.Vec2好像没有fuzzyEquals方法啊。文档:http://docs.cocos.com/creator/api/zh/classes/Vec2.html
另外 https://github.com/cocos-creator/engine/tree/master/cocos2d/core/value-types 这里面的类,基本上有equals 方法的都是直接浮点数相等比较了,比如 CCRect:
proto.equals = function (other) {
return other &&
this.x === other.x &&
this.y === other.y &&
this.width === other.width &&
this.height === other.height;
};
再如 CCSize:
/**
再补充一个:
/**
所以,应该可以看出,cocos很多地方都是直接用 ===比较浮点数的,使用这些函数是否会有风险呢?
是会有风险的,风险用户应该自己清楚,如果比较的是整型,那么正常都没问题,如果包含小数点,就有可能返回错误的结果。我们会在 API 文档里补充这一点。
另外,我查了 Unity、Pixi 和 .net 的同类实现,都是会返回是否切实相等。不会帮用户进行精度(epsilon)计算。
我也查了两个开源引擎,ogre是直接用==比较,irrlicht是会使用epsilon比较。感觉使用epsilon对用户更友好吧,其实unity使用的时候也很是不便
另外,由于js没有整形,即数的内部存储都是iee754浮点数,所以使用equals方法的时候,如何确保传入的是没有小数位的数呢?既然是比较,至少有一个参数是变量吧,这个变量经过游戏逻辑各种运算,很难说这个数就是没有小数位,更何况还有很多有小数位的数在使用,所以用户还是得自己使用epsilon进行比较,equals方法可以用,但用了也不知道会不会有问题,实在是有些鸡肋。建议增加一个fuzzyEquals方法,或者一个内置了误差比较的equals版本
虽然是浮点数,可是如果存的是整数的话一般都会在有效精度内,不存在比较失败的可能。
equals 主要是引擎用来统一处理,实现 instantiate,实现动画系统用的。一般也就是和 0, 0 进行比较而已。
equals 一般不会用在游戏中需要计算的地方,一般也就用来比较一下是否仍然在起点位置,我不太觉得有需要修改的必要。
游戏逻辑中,如果需要计算坐标,比如你做缓动,判断是否会到达终点,那么坐标通常是用距离来比较的。
比如
var arrived = pos.sub(dest).magSqr() < 0.01;
if (arrived) {
// stop
}
else {
pos = pos.lerp(dest, 0.2);
}
一般不会有人在这种很容易产生精度问题的地方用 equals 吧?谁能保证距离一定能移动到?
像这里,使用 pos.magSqr(dest) < 0.01 来代替 equals 是比较常用的做法。
这个情况我踩过,运动到x=90的地方 打印出来可能就是89.9xx或者90.000xx多点。比较要谨慎~