我正在研究一个问题,我应该写一种方法
如果x * x可以容纳32位整数,则返回1,否则返回0。
我以为我可以检查数字是否大于46340(可以使用2的补码二进制表示形式表示的最大数字的平方根。)但是我不能,因为我限于使用最大255。
/*
* squaredOK - Return 1 if x*x can
fit
in
a 32-bit integer, and 0 otherwise.
* Examples: squaredOK(10) = 1
* squaredOK(1000000) = 0
* Legal ops: ! ~ & ^ | + - << >>
* Max ops: 20
*/
int squaredOK(int x) {
return ; /* no idea */
}
好吧,阅读评论后,我决定添加限制: 仅使用以下内容:
答案 0 :(得分:0)
根据代码注释,允许使用<<
和|
,因此您可以使用shift和or来产生一个更大的常量。这在将数字转换为十六进制时更简单:< / p>
46340 == 0xb504 == (0xB5 << 8) | 0x04
这不能完全解决问题,因为您似乎没有可用的比较(此限制在以后添加)。
在这种情况下,我希望这个问题是针对无符号整数的。在这里,您只需要检查是否设置了16个高位。幸运的是,!
在允许的操作列表中,因此您可以仅对右移16的数字不应用。
如果问题实际上出在带符号的数字上,那就更棘手了。您可以使用-
和一个检查符号位来替换比较运算符:
int squaredOK(int x) {
return (x - ((0xB5 << 8) | 4)) >> 31
}
为了更加安全,您可以使用双精度not(!!)来防止带有符号数字的实现特定的右移行为。
答案 1 :(得分:0)
这个问题的定义模糊不清,我认为您已经以某种方式对其进行了解释,这使您自己变得比需要困难。
如果将“适合32位整数”解释为 unsigned 32位整数,则最大值(2 32 )的平方根为更方便的值(2 16 )。我很确定这就是原意。
答案 2 :(得分:0)
您要实施abs(x) < 46341
(或0xb505
)但有一些愚蠢的限制。
对于带符号的32位int
来说,这个问题似乎非常困难,对于普通的int
来说,甚至更困难。
如果问题的格式错误并且适用于32位无符号整数,则可以采用以下解决方案:
/*
* squaredOK - Return 1 if x*x can fit in a 32-bit integer, and 0 otherwise.
* Examples: squaredOK(10) = 1
* squaredOK(1000000) = 0
* Legal ops: ! ~ & ^ | + - << >>
* Max ops: 20
*/
int squaredOK(uint32_t x) {
return !(x >> 16);
}
如果该问题确实适用于带有二进制补码表示法的32位带符号的int
,则可以验证它是否适用于所有值:
#include <limits.h>
#include <stdio.h>
#include <stdint.h>
int squaredOK(int32_t x) {
return !(x + 0U >> 31) & x - (0xB5 << 8 | 5U) >> 31 |
x + 0U >> 31 & !(x + (0xB5 << 8 | 4U) >> 31);
}
int main() {
long long x;
for (x = INT32_MIN; x <= INT32_MAX; x++) {
if (squaredOK(x) != (x * x <= INT32_MAX)) {
printf("failed on %lld\n", x);
return 1;
}
}
return 0;
}
说明:
x < 46341 && x > -46341
(x >= 0 && x < 46341) || (x < 0 && x > -46341)
(x >= 0 && x - 46341 < 0) || (x < 0 && x + 46340 >= 0)
(x >= 0 && x - (0xB5<<8|5) < 0) | (x < 0 && x + (0xB5<<8|4) >= 0)
(!(x+0U>>31) & (x - (0xB5<<8|5U)) >> 31) | ((x+0U>>31) & !((x + (0xB5<<8|4U)) >> 31)
通过转换为unsigned
并右移31位来测试符号位。
转换为unsigned
是隐式的,其中一个操作数是无符号的,因此x + 0U
将x
转换为无符号类型。其他表达式也使用类似的技巧。
答案 3 :(得分:-1)
答案假定未签名,请针对您的特定作业进行修改
如果在第三个或第四个字节上设置了任何位,则您无法容纳它,因此您的老师想要的是这样的东西:
//check the third byte for bits //check the 4th byte for bits
retbool = (((unsigned char)(x >> 16) & 0xFF) | ((unsigned char)(x >> 24) & 0xFF)));
如果设置了这些字节中的任何位,那么您将无法在32位int中拟合平方。如果问题是关于unsigned int 32的话,那将是结尾,但是由于0xFFFF * 0xFFFF大于maxsigned int,因此还必须使用符号位对第二个字节进行一些检查。
由于您永远不可能真的有一个负平方,因此未签名的版本应该是替代答案,但我没有写此作业。
编辑(如果位模式是唯一的,则必须屏蔽...)
#include <stdio.h>
int doesFit(int x);
typedef unsigned char uchar;
typedef unsigned short ushort;
#define MAX_POS_SQUARE 46340
#define MAX_NEG_SQUARE -46340
int main(void) {
int x=MAX_NEG_SQUARE -2;
int fits = -1;
int prevoiusly_fit = 0;
for(;x<MAX_POS_SQUARE+5;x++){
fits = doesFit(x);
if(!fits && prevoiusly_fit){
printf("%d didnt fit and %d did\n",x,x-1);
}
else if(fits && !prevoiusly_fit){
printf("%d fit and %d did not\n",x,x-1);
}
prevoiusly_fit = fits;
}
return 0;
}
int doesFit(int x){
uchar bits_left = 16;
ushort pos_mask = ((0xb5 << 8) | 0x04);
ushort neg_mask = ((0xb5 << 8) | 0x05);
ushort x_16_low = (((-x) & 0xff << 8 ) | (-x) & 0xff); //used in negative case
ushort x_16_high = (-x)>>16; //used in negative case
//Handle the negative case
//printf("0x%04x x: 0x%04x x_16_low: 0x%04x x_16_high:", x, x_16_low, x_16_high);
if(x>>31){
//how can you tell if a value x < -46340
if( (x_16_high & 0xFF) | (x_16_high >>8 & 0xFF)){
//doesnt fit, maybe dont use compliment use ! if accidental promotion occurs
printf("bailing out when x=%d\n", x);
return 0;
}
while(bits_left){
--bits_left;
if(x_16_low & (1 << bits_left)){
if(!(neg_mask & (1 << bits_left))){
return 0;
}
}
else if(!(x_16_low & (1 << bits_left))){
if(neg_mask & (1 << bits_left)){
return 1;
}
}
//high bits matched with max value bits, cant tell yet, keep masking.
}
}
else{ //handle the positive case
//how can you tell if a value x > 46340
if( (x >> 16 & 0xFF) | (x >>24 & 0x7F)){
//doesnt fit, return false
return 0;
}
while(bits_left){
--bits_left;
if(x & (1 << bits_left)){
if(!(pos_mask & (1 << bits_left))){
return 0;
}
}
else if(!(x & (1 << bits_left))){
if(pos_mask & (1 << bits_left)){
return 1;
}
}
//high bits matched with max value bits, cant tell yet, keep masking.
}
}
return 1; //Must be the exact size to fit to get to this return
}
输出:
-46341适合,而-46342不适合
46341不适合,46340不适合
我觉得我只是在浪费一个小时来做这些家伙的功课...