查找有符号和无符号整数是偶数还是两者都是奇数

时间:2017-07-20 18:36:02

标签: c++ c++11 c++14

我有一个int m和一个unsigned int j,想要确定它们是偶数还是两者都是奇数。

过去我一直在使用

if((int(j)+m)%2)

抓住只有一个奇怪的情况。但是我担心int错误地改变了j的奇偶性。

其中任何一个遇到问题吗?

if(!(j%2)!=!(m%2))
if(bool(j%2)!=bool(j%2))

我知道

if(j%2!=m%2)

不起作用,因为当-1为否定时,'m%2'会产生m,无论true的值是什么,总是会评估为j%2

6 个答案:

答案 0 :(得分:64)

不要使用%。这是一个需要位掩码的问题:

bool same_parity = (i & 0x1) == (j & 0x1);

无论i的符号如何,这都有效,因为该表达式的结果将始终为01

答案 1 :(得分:56)

> git status
rebase in progress; onto 55d9292
You are currently rebasing branch 'master' on '55d9292'.
  (fix conflicts and then run "git rebase --continue")
  (use "git rebase --skip" to skip this patch)
  (use "git rebase --abort" to check out the original branch)

Unmerged paths:
  (use "git reset HEAD <file>..." to unstage)
  (use "git add <file>..." to mark resolution)

        both modified:   file

no changes added to commit (use "git add" and/or "git commit -a")

if (1 & (i ^ j)) { // Getting here if i is even and j is odd // or if i is odd and j is even } ^按位运算符,如果它们具有相同的值,则会检查两个数字中的每个位。例如,如果exclusive-or的二进制表示为i0101j,那么1100将评估为i ^ j,因为它们是第一个最后一位是不同的,而中间位是相同的。

1001&按位运算符,如果它们都是and,则会检查两个数字中的每个位。

由于每个数字的最后一位确定它是偶数还是奇数,1如果它们都是偶数或奇数将评估为i ^ j,否则...xxx0将评估为...xxx1 1}}无所谓,无论如何我们都不看它们。由于x实际上是1,如果...00011 & (i ^ j)都是偶数或奇数,0评估为ij否则。

这适用于无符号数,2s补码和符号和幅度的任意组合,但如果只有一个是负数,则不适用于罕见的1s补码。

答案 2 :(得分:20)

添加两个整数会增加它们的奇偶校验,因此解决方案就是:

if ( (j + m) % 2 )

无符号环绕不会干扰此属性,因为它以模数UINT_MAX+1完成,这是偶数。

此解决方案不依赖于任何特定于实现的细节,例如负数表示。

脚注:我很难理解为什么有这么多其他答案会让位移,位补码,XOR等问题变得复杂化。不幸的是,IMO,它有时会在C中得到颂扬或者C ++社区编写棘手的代码而不是简单的代码。

答案 3 :(得分:16)

投放大于unsigned intINT_MAX的{​​{1}}并不能保证返回合理的值。结果未定义。

int投射到int始终会产生已定义的行为 - 对于某些unsigned int来说,它会对数mod 2^k进行数学运算,其中每个正kint小于2^k

if((int(j)+m)%2)

应该是

if((j+unsigned(m))%2)

代替。

if((j%2)==(unsigned(m)%2))

是查看两者是否具有相同奇偶校验的最简单方法。移动到无符号的又名mod 2^k将保持奇偶校验,而无符号%2正确地返回奇偶校验(而不是负奇偶校验)。

答案 4 :(得分:6)

不要太聪明

  

其中任何一个遇到问题吗?

if(!(j%2)!=!(m%2))
if(bool(j%2)!=bool(j%2))

我看到的一个问题是可读性。对于其他人(或您未来的自己)来说,它应该做什么或者实际做什么可能并不明显。

你可以通过花一些额外的线条来表达更多:

#include <cmath>

const bool fooIsEven = foo % 2 == 0;
const bool barIsEven = std::abs(bar) % 2 == 0;
if (fooIsEven == barIsEven)
{
  // ...
}

还要考虑实现一个正确命名的函数,该函数提供两个给定整数类型的奇偶校验的比较。这不仅可以清除您的代码,还可以防止您重复自己。

编辑:通过调用std :: abs

替换了强制转换

答案 5 :(得分:-1)

这可以简化:

if(!(j%2)!=!(m%2))
if(bool(j%2)!=bool(j%2))

为:

if ((abs(m) % 2) != (j % 2))

一定要包含math.h

#include <math.h>

绝对值将取消存储中最左边的符号位。

将signed转换为unsigned是可以的,并且在C99中定义。

找到此resource

按位运算符也应该与C99编译器一起使用,并且具有较小最大值的符号将转换为更大(签名为无符号)。