c++ 即使将变量从int改为double再改为long,给定的代码也无法处理较大的值

sshcrbum  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(81)

这就是问题陈述。

  • 基数10的补码

一个整数的补码是当你把它的二进制表示中的所有0翻转为1和所有1翻转为0时得到的整数。
例如,整数5在二进制中是“101”,它的补码是“010”,即整数2。给定一个整数n,返回它的补码 *
我看到了一些解决这个问题的方法,使用位屏蔽,这是我得到的东西,但首先我想知道为什么下面给出的代码不工作?
它适用于较小的值,但输入:299475输出:224816预期输出:224812
这个问题似乎在更大的价值观上持续存在。

#include <math.h>
class Solution {
#include <math.h> 
public:
int bitwiseComplement(int n) {
long a = 0;
int i = 0;
if ( n == 0) { 
     return 1;
}
while ( n != 0 ) { 
    int b = n & 1;
    if ( b == 1) { 
        b = 0;
    }
    else if (b == 0){ 
        b = 1;
    }
    n = n >> 1;
    a = a + (b * pow(10, i));
    i++;
        
}
long sol = 0;
int k = 0;
while ( a != 0) { 
    int b = a % 10;
    sol = sol + (b * pow(2, k));
    k++;
    a = a/10;
}
return sol;}
};

字符串

jljoyd4f

jljoyd4f1#

显然,你正在计算一个数字,它的十进制表示看起来像原始数字的二进制表示。
问题是这些数字比原来的数字大得多(例如8得到1000,16得到10000,...)。
1010已经不适合32位了(假设int-有符号或无符号-在你的系统上有这个大小)-所以你可以安全地转换这种方式而不丢失信息的最大数字是210 - 1 = 1023,任何更大的数字都会引起溢出-甚至更糟:因为你选择了 * 有符号 * 整数实际上 * 未定义的行为 *。
现在,许多系统上的long(例如32位Linux或Windows -与64位Linux相比)与int大小相同,因此在这种情况下也没有帮助;你可能会尝试unsigned long long,或者,为了不依赖于特定于操作系统的大小,uint64_t来自<cstdint>头。10的最大幂仍然适合19,所以你仍然可以计算它的最大表示是220 - 1 = 1 048 575。但是这仍然很小...
相比之下,double的精度甚至比大小相等的有符号整数更差,因为它使用1位用于符号,11位用于指数,剩余52位用于尾数,因此53位用于值,包括隐式值,从而允许精确表示1015,因此,216 - 1 = 65535是您可以计算表示的最大值。
这个问题的解决方案是跳过10进制的中间表示,直接计算2进制的补码:

unsigned int bit = 0;
while(n) // uint32_t!
{
   c |= !(n & 1) << bit++; // or 1 - (n & 1), if you prefer...
   n >>= 1;
}

字符串

相关问题