在String.prototype.slice()中,.slice(0,-0)和.slice(0,+0)应该输出相同的结果吗?

11

我在尝试优化代码高尔夫游戏中的字符串复数时遇到了这个怪癖。 我想将字符串写成复数形式,然后使用substr有条件地剪切最后一个字符:

var counter = 1;
var myText = counter + " units".substr(0, 6-(counter===1));

没问题 - 它做到了我想要的。但是看了一下MDN docs for String.prototype.slice(),我发现可以通过将负零作为第二个参数传递给函数来使它更短。从文档中可以看出:

endSlice

可选。要结束提取的基于零的索引。如果省略,slice() 将一直提取到字符串末尾。如果为负数,则当作 sourceLength + endSlice 处理,其中 sourceLength 是字符串的长度(例如,如果 endSlice 为 -3,则会被视为 sourceLength - 3)。

var myText = counter + " units".slice(0,-(counter===1));

counter 等于1 时,这将评估为 .slice(0,-1),它将从字符串中切掉最后一个字母,否则它将评估为 .slice(0,-0),根据文档应该意味着从操作的字符串长度中减去了0个字符。

事实上,String.prototype.slice 将 -0 和 +0 视为相同。我想知道这是否是一种惯例,即将 -0 视为与 +0 相同 (例如,-0 === +0 的结果为 true)。 我想看看 String.prototype.substr,但在该函数中 +0 和 -0 应该被同样处理。

有没有人对此有更深入的了解?在语言设计中是否有一些基本约定,规定带符号零是一种语言特性,它应该被忽略,除了某些情况(例如 1/-0)?

简而言之,很遗憾我不能开玩笑说通过“切片”赢得代码高尔夫比赛。


标准还说:“如果end为负数,则将其视为sourceLength + end,其中sourceLength是字符串的长度。”我认为他们在这里对“负数”一词不够小心。 - user2357112
你会如何实现“如果是负数”的判断?在我的代码中,我通过 if (val < 0) 进行测试,考虑到 -0 < 0 返回 false ,这也是应该的...请想象一下,如果我们必须编写所有的代码来区分 -0+0 的情况... - nnnnnn
1
第二个参数在与零进行比较之前会被强制转换为整数(通过ToLimit)。整数没有负零。这在ECMA规范中详细解释(只有真正的痛苦之徒才会阅读)。MDN是一个简化的描述。 - Raymond Chen
“-0”只是实际世界中零的浮点表示,就像“+0”一样。 - Salman A
在研究过程中,我发现Javascript确实提供了一些测试正零和负零的方法。例如:1/-0 === -Infinity1/0 === Infinity - jamesinc
显示剩余2条评论
1个回答

2
从数学角度来看,不存在负零。正数是大于零的任何数字,负数是小于零的任何数字。零不属于这两种情况。因此,我想您所描述的行为是正确的。

实数可以是有理数或无理数;代数数或超越数;可以是正数、负数或零。

https://en.wikipedia.org/wiki/Real_number

尽管在编程中我们使用浮点数,它们是实数的近似值,但有一个概念叫做“-0”。它可能代表一个负数,但太接近零无法用其他方式表示。详情请参见http://www.johndcook.com/blog/2010/06/15/why-computers-have-signed-zero/
关于你的 JavaScript,你可以这样写:
var counter = 1;
var myText = counter + " unit" + (counter > 1 ? "s" : "");

浮点数不是“早于”IEEE754的吗? 不确定标准本身是否会将任何语义(例如“负数太接近零无法以其他方式表示”)放入-0值中,但我很怀疑。 - zerkms
@zerkms - 我认为这不是一个定义问题,而是一个物理限制,迫使数字在某个时刻被舍入。无论如何,我不是这个问题的专家,也从未遇到过这个问题。我只是想指出,在编程中存在这个概念,尽管它在数学上并不相关。请随意编辑答案(或添加新答案)以获取更多详细信息。 - Hugo Silva
答案很好,只有一点需要注意:它将一些额外的点放得太靠近零,“这可能是负数的表示形式”。我认为这不正确:你可以确切地拥有-0并且确切地意味着那个值,因此它不会是一个近似或舍入误差。我会完全删除那部分。 - zerkms
当然,有很多方法可以编写我的示例...我最终使用了一个略微令人不安的硬编码长度与substr:counter + " units".substr(0,6-(counter===1)),但像你的普通三元运算符一样是我认为最短的方式。编辑:请不要深究我的代码...我正在寻找故意晦涩的方法来完成这个任务! - jamesinc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接