测试一个值是奇数还是偶数。

241

我决定创建一个非常简单的算法,来实现简单的isEvenisOdd函数:

function isEven(n) {
  n = Number(n);
  return n === 0 || !!(n && !(n%2));
}

function isOdd(n) {
  return isEven(Number(n) + 1);
}

如果n处于特定参数中,那么这样做是可以的,但对于许多情况来说是失败的。因此,我开始创建强大的函数,以便尽可能多地处理正确的情况,只测试在JavaScript数字限制范围内的整数,其他所有内容都返回false(包括+和-无穷大)。请注意,零是偶数。

// Returns true if:
//
//    n is an integer that is evenly divisible by 2
//
// Zero (+/-0) is even
// Returns false if n is not an integer, not even or NaN
// Guard against empty string

(function (global) {

  function basicTests(n) {

    // Deal with empty string
    if (n === '') 
      return false;

    // Convert n to Number (may set to NaN)
    n = Number(n);

    // Deal with NaN
    if (isNaN(n)) 
      return false;

    // Deal with infinity - 
    if (n === Number.NEGATIVE_INFINITY || n === Number.POSITIVE_INFINITY)
      return false;

    // Return n as a number
    return n;
  }

  function isEven(n) {

    // Do basic tests
    if (basicTests(n) === false)
      return false;

    // Convert to Number and proceed
    n = Number(n);

    // Return true/false
    return n === 0 || !!(n && !(n%2));
  }
  global.isEven = isEven;

  // Returns true if n is an integer and (n+1) is even
  // Returns false if n is not an integer or (n+1) is not even
  // Empty string evaluates to zero so returns false (zero is even)
  function isOdd(n) {

    // Do basic tests
    if (basicTests(n) === false)
      return false;

    // Return true/false
    return n === 0 || !!(n && (n%2));
  }
  global.isOdd = isOdd;

}(this));

有人能看到上面任何问题吗?是否有更好(即更准确、更快或更简洁而不会使代码难以理解)的版本?

有关其他语言的帖子很多,但我似乎找不到ECMAScript的确定性版本。


可能是如何在JavaScript中确定一个数字是否为奇数的重复问题。 - nyedidikeke
25个回答

486

使用模运算:

function isEven(n) {
   return n % 2 == 0;
}

function isOdd(n) {
   return Math.abs(n % 2) == 1;
}
你可以通过以下代码来检查JavaScript中的任何值是否可以强制转换为数字:

你可以通过以下代码来检查JavaScript中的任何值是否可以强制转换为数字:

Number.isFinite(parseFloat(n))

最好在 isEvenisOdd 函数之外进行此检查,这样您就不必在两个函数中重复错误处理。


2
0.1NaN与上述函数配合良好。空数组有点麻烦,因为空数组等同于0... - Steve Mayne
4
@Alin - 我已经添加了数字检查。我不确定你何时需要算术函数显式处理其他数据类型的情况,但如果这是提问者想要的...... - Steve Mayne
2
return n == parseInt(n); 改为 return n === parseInt(n); 怎么样? - JiminP
3
我记得在某个地方看到过,当检查奇数时应该检查 n % 2 !== 0,因为根据语言不同,它并不一定是1。编辑:啊,这就是.abs调用的作用。那就算了。 - ptf
4
@Andy Ray - 你不能用!isEven(number)来表示isOdd,因为这意味着0.1是奇数,但它并不是偶数。 - Steve Mayne
显示剩余8条评论

110

我更喜欢使用位测试:

if(i & 1)
{
    // ODD
}
else
{
    // EVEN
}

这个测试检查第一位是否为1,表示一个奇数。


6
当然。在二进制数学中使用模运算应该是非法的 ;) - aceofspades
5
三元运算符: i & 1 == 1 ? console.log("奇数") : console.log("偶数"); 此外,对于位级效率加1(在JavaScript中不太常用)。 - Jacksonkr
24
请注意,JavaScript 中没有“位级效率”,因为 JavaScript 中的所有数字都是浮点数,使用位运算符意味着首先将其转换为整数,然后执行操作,最后再将其转换回浮点数。 - poke
1
@poke 正确,它们是数字类型,但知道强类型语言的效率还是很好的。 - Robert Brisita
1
@AndrewCastellano 你正在测试单个位而不是整个 i 的值。任何大于 0 的数字都将为 true,但这并不意味着它是奇数还是偶数。请查看:http://bitwisecmd.com/ 并根据输入的数字查看位的扩展。 - Robert Brisita
显示剩余4条评论

9
以下怎么样?我只在IE中测试过,但它非常愿意处理任何长度的表示数字的字符串,实际上是整数或浮点数的数字,当传递布尔值、未定义、null、数组或对象时,两个函数都返回false。(当传入一个字符串时,你可以选择是否忽略前导或尾随空格 - 我假设它们不被忽略,并且会导致两个函数都返回false。)
function isEven(n) {
   return /^-?\d*[02468]$/.test(n);
}

function isOdd(n) {
   return /^-?\d*[13579]$/.test(n);
}

3
我的实现中,isEven(2.122e3) 返回 true,但 isEven("2.122e3") 返回 false。相反,我的 isEven() 在处理非常大的数字时会失败,因为在将它们转换为字符串进行正则表达式测试时,JS 会将它们放入指数格式中。哎呀。 - nnnnnn
@MartijnScheffer - 随意给我发账单,因为你将不得不购买所有额外的内存。请注意,问题确实包括从其他类型转换为数字,并且显然我在这里建议的重点是拥有一个简单的一行函数来处理数字和字符串。当然,根据我的评论,这实际上并没有处理所有可能的情况,但仍然可能有用-正则表达式是验证用户输入数据的最简单方法,最初将是一个字符串。 - nnnnnn
1
我在这里发表了评论吗?我没有看到它,但如果您想要一个评论,我可以发一个!这不是正确的解决方案,这会慢上数百倍,我们讨论的是数字而不是字符串,如果您想检查一个字符串是否为有效的整数,那么可以单独处理。 - Martijn Scheffer
@MartijnScheffer - 是的,你曾经有一条评论,但似乎在我的回复后被删除了。请注意,此问题不仅涉及数字,OP的代码还包括其他类型的转换。无论如何,感谢您的反馈。 - nnnnnn

8
注意:此外还有负数。
function isOddInteger(n)
{
   return isInteger(n) && (n % 2 !== 0);
}

在哪里

function isInteger(n)
{
   return n === parseInt(n, 10);
}

1
这里不需要使用 parseInt 的基数吗? - blablabla
@blablabla 是的,不是所有的实现都假定基数为10。 - Rodrigo
良好的负值引用。Robert Brisita的答案(稍后添加)也涵盖了这一点。 - Jacksonkr

5
完成罗伯特·布里西塔(Robert Brisita)的位测试。
if ( ~i & 1 ) {
    // Even
}

5
var isOdd = x => Boolean(x % 2);
var isEven = x => !isOdd(x);

4
为什么不这样做:
    function oddOrEven(num){
        if(num % 2 == 0)
            return "even";
        return "odd";
    }
    oddOrEven(num);

甚至可以这样写:function isEven(num) { return num % 2 == 0 }` - chiapa
4
使用ES6语法:const oddOrEven = num => num % 2 === 0 ? 'even' : 'odd',意思是根据输入的数字是偶数还是奇数返回相应的字符串。如果输入的数字可以被2整除,则返回'even',否则返回'odd'。 - enguerran

3
我们只需要一行代码就可以完成这个!
这里提供了一个新的、替代性的方法来完成这个任务,使用了 JS 函数的新 ES6 语法以及 if-else 语句的 一行语法
const isEven = num => ((num % 2) == 0);

alert(isEven(8));  //true
alert(isEven(9));  //false
alert(isEven(-8)); //true

2
这个更短,写作 let isEven = num => num % 2 === 0。:-) 但实际上它和其他许多答案没有什么不同。 - RobG
1
进一步解释另一个评论,(num % 2) == 0 已经返回一个布尔值,你不需要在之后显式地返回。 - Marie

2
一些。
x % 2 == 0; // Check if even

!(x & 1); // bitmask the value with 1 then invert.

((x >> 1) << 1) == x; // divide value by 2 then multiply again and check against original value

~x&1; // flip the bits and bitmask

1
var isEven = function(number) {
    // Your code goes here!
    if (number % 2 == 0){
       return(true);
    }
    else{
       return(false);    
    }
};

4
“if(<expression>)return true else return false”这种写法总是可以简化为“return(<expression>)”,因为在一个if语句中,<expression>已经是一个布尔值。 - Gerold Broser
说返回不是一个函数,就像说if不是一个函数一样,即使在返回值时使用括号(即使它们在这里没有用)也是完全有效的。 - Martijn Scheffer

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