js浮点数能直接===比较吗?

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不好不要骗我。。。
看看这个 https://blog.csdn.net/songfreeman/article/details/78175516

问题是这是cocos的引擎代码啊。。。所以我确认一下,毕竟我js没学好
@jare

1赞

https://blog.csdn.net/asdbbs/article/details/7039345 看一下这个有没有帮助

用区间比较啊. 大于等于 小于等于 .

赞一个。那么cc.Vec2的equals方法就是不对的了。开发团队认为需要修改吗?
@jare @panda

浮点数计算在 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:

/**

  • !#en TODO
  • !#zh 当前 Size 对象是否等于指定 Size 对象。
  • @method equals
  • @param {Size} other
  • @return {Boolean}
  • @example
  • var a = new cc.size(10, 10);
  • a.equals(new cc.size(10, 10));// return true;
    */
    proto.equals = function (other) {
    return other &&
    this.width === other.width &&
    this.height === other.height;
    };

再补充一个:

/**

  • !#en Check whether a point’s value equals to another.
  • !#zh 判断两个向量是否相等。
  • @method pointEqualToPoint
  • @param {Vec2} point1
  • @param {Vec2} point2
  • @return {Boolean}
    */
    cc.pointEqualToPoint = function (point1, point2) {
    return point1 && point2 && (point1.x === point2.x) && (point1.y === point2.y);
    };

所以,应该可以看出,cocos很多地方都是直接用 ===比较浮点数的,使用这些函数是否会有风险呢?

@panda @jare @wangzhe

是会有风险的,风险用户应该自己清楚,如果比较的是整型,那么正常都没问题,如果包含小数点,就有可能返回错误的结果。我们会在 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多点。比较要谨慎~