Javascript 纯函数给出严格相等的参数,得到非严格相等的结果
下面是一个Javascript 纯函数给出严格相等的参数,得到非严格相等的结果,javascript,Javascript,下面是一个f,其中f(a)!=f(b)尽管对于a和b的某些值,a===b(注意严格的等式): var f = function (x) { return 1 / x; } +0 === -0 // true f(+0) === f(-0) // false 这些函数的存在可能导致难以发现bug。还有其他我应该厌倦的例子吗?1/+0是无穷大,1/-0-Infinity,而+0=-0 这可以通过ECMA将-0定义为等于+0这一特殊情况来解释,而在其他操作中,这两个值保留其不同的属性,这会导
f
,其中f(a)!=f(b)
尽管对于a
和b
的某些值,a===b(注意严格的等式):
var f = function (x) {
return 1 / x;
}
+0 === -0 // true
f(+0) === f(-0) // false
这些函数的存在可能导致难以发现bug。还有其他我应该厌倦的例子吗?
1/+0
是无穷大,1/-0
-Infinity,而+0=-0
这可以通过ECMA将-0定义为等于+0这一特殊情况来解释,而在其他操作中,这两个值保留其不同的属性,这会导致一些不一致
这是可能的,因为语言,事实上不是
其他的例子,如果有的话,应该是基于同样的人为平等,并且没有其他这样的例外,所以可能没有其他的例子
如果它有任何用途,我们可以通过向其添加0
来确保0
不是-0
:
var f = function(x) {
return 1 / (x + 0);
}
f(+0) === f(-0)
这种行为是完全正确的,因为在数学理论中,
-0==+0
是正确的,1/(-0)==1/(+0)
不是,因为-inf!=+inf
编辑:尽管我真的很惊讶javascript实际上可以处理这些数学概念
EDIT2:此外,您描述的现象完全基于这样一个事实,即您被零除,您至少应该从中看到一些奇怪的行为。有许多这样的函数,下面是另一个例子
function f (a) {
return a + 1;
}
1==“1”
但是f(1)!=f(“1”)
这是因为平等是一个微妙的概念
也许更可怕的是在你的例子中-0==+0 我不太确定这有多可怕;-)Javascript不是一种纯粹的语言,+/-0的存在以及-0和+0的相等是特定的,并且是“定义良好的”,即使有时可能令人惊讶。(例如,即使NaN!=NaN始终为真也有很好的定义。)
发件人:
根据IEEE 754标准,负零和正零应与通常的(数值)比较运算符进行相同的比较
从技术上讲,由于f
的两个输入不同,因此结果也可能不同。值得一提的是,Haskell会将0==-0
视为真,但将(1/0)==(1/-0))
视为假
然而,我确实发现这是一个有趣的问题
快乐的编码。是的,因为
NaN!==NaN
var f = function (x) { return Infinity - x; }
Infinity === Infinity // true
f(Infinity) === f(Infinity) // false
f(Infinity) // NaN
产生NaN
且其参数可以严格相等的其他一些示例:
0/0
Infinity/Infinity
Infinity*0
Math.sqrt(-1)
Math.log(-1)
Math.asin(-2)
在ECMAScript 3中,
==
表现令人惊讶的另一个例子是使用连接的函数。考虑这样一个例子:
function createConstantFunction(result) {
return function () {
return result;
};
}
var oneReturner = createConstantFunction(1); // a function that always returns 1
var twoReturner = createConstantFunction(2); // a function that always returns 2
允许实现“连接”这两个函数(见规范§13.2),如果实现了,则即使这两个函数做不同的事情,oneReturner===tworereturner
也将是true
(见§13.1.2)。与这些类似:
// a perfect forwarder: returns a sort of "duplicate" of its argument
function duplicateFunction(f) {
return function (f) {
return f.apply(this, arguments);
};
}
var myAlert = duplicateFunction(alert);
console.myLog = duplicateFunction(console.log);
这里的一个实现可以说myAlert===console.myLog
,尽管myAlert
实际上等同于alert
和console.myLog
(但是,ECMAScript 3的这一方面没有保留在ECMAScript 5中:不再允许加入函数。)我知道这个示例的解释。我对其他示例感兴趣。我可以想到一组函数,其中
f(-0)!=f(+0)
,但imo javascript首先应该将-0===+0
计算为false。不要认为会有任何例子不是基于-0===+0
你能“证明”没有其他例子吗?我怎么能?证明必须包含整个javascript语言规范。经验法则<代码>-0==+0由于复杂的数学背景,我不知道如何将它们翻译成可以理解的英语,所以只能计算为真。好了,这是唯一的基地,对于它来说f(x)!=f(y)
而x==y
。这使用=
运算符。使用==
操作符可以使其联机。这是编程问题吗?我不确定我是否完全理解这个问题。@Gabe:严格的平等,顾名思义,应该是严格的。我提供的函数表明严格相等实际上没有那么严格,这对我来说确实是个问题。@Random:严格相等只意味着不执行类型转换<代码>-0和+0
都是数字。你为什么要区分它们呢?无论如何,被零除是没有定义的,其他语言在这种情况下会抛出一个错误。因为属性a===b
意味着f(a)==f(b)
对于纯函数f
是一个很好的选择,你不这样认为吗?一般来说可能。但是在JavaScript中,如果定义+0!==-0,则这意味着Math.round(-5/10)!=0
。这可能是一种更普遍的情况,并且会产生更多的问题。你还必须考虑实际的方面,而不仅仅是理论方面的问题。这个例子基本上和我的一样。你有没有一个和我的有点不同的呢?我本来以为问题是为什么f(+0)!=f(-0);我已经更新了答案。考虑到这种违反直觉的情况是由于人工技术声明导致的,==
运算符在传递两个不同的值-0和+0时必须返回true,如果没有其他类似的异常,那么可能没有其他类似的情况。生成类似于此的其他情况的唯一方法是声明如果传递值1和2,则===运算符返回true。或者两个相等的值是不同的,比如NaN,事实上。你能做出这样的声明吗?!这可能是唯一的办法