我有一个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
是
答案 0 :(得分:64)
不要使用%
。这是一个需要位掩码的问题:
bool same_parity = (i & 0x1) == (j & 0x1);
无论i
的符号如何,这都有效,因为该表达式的结果将始终为0
或1
。
答案 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
的二进制表示为i
且0101
为j
,那么1100
将评估为i ^ j
,因为它们是第一个最后一位是不同的,而中间位是相同的。
1001
是&
按位运算符,如果它们都是and
,则会检查两个数字中的每个位。
由于每个数字的最后一位确定它是偶数还是奇数,1
如果它们都是偶数或奇数将评估为i ^ j
,否则...xxx0
将评估为...xxx1
1}}无所谓,无论如何我们都不看它们。由于x
实际上是1
,如果...0001
和1 & (i ^ j)
都是偶数或奇数,0
评估为i
,j
否则。
这适用于无符号数,2s补码和符号和幅度的任意组合,但如果只有一个是负数,则不适用于罕见的1s补码。
答案 2 :(得分:20)
添加两个整数会增加它们的奇偶校验,因此解决方案就是:
if ( (j + m) % 2 )
无符号环绕不会干扰此属性,因为它以模数UINT_MAX+1
完成,这是偶数。
此解决方案不依赖于任何特定于实现的细节,例如负数表示。
脚注:我很难理解为什么有这么多其他答案会让位移,位补码,XOR等问题变得复杂化。不幸的是,IMO,它有时会在C中得到颂扬或者C ++社区编写棘手的代码而不是简单的代码。
答案 3 :(得分:16)
投放大于unsigned int
到INT_MAX
的{{1}}并不能保证返回合理的值。结果未定义。
将int
投射到int
始终会产生已定义的行为 - 对于某些unsigned int
来说,它会对数mod 2^k
进行数学运算,其中每个正k
为int
小于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编译器一起使用,并且具有较小最大值的符号将转换为更大(签名为无符号)。