我的任务看起来很简单,我需要计算表示一个变量整数所需的最小字节数(例如,如果整数是5,那么我想返回1;如果整数是300,我想返回2 )。不是指数据类型 int,正如注释中指出的那样,它始终只是 sizeof(int),我指的是数学整数。 我几乎有一个解决方案。这是我的代码:
int i;
cin >> i;
int length = 0;
while (i != 0) {
i >>= 8;
length++;
}
问题在于,这不适用于任何负数(我无法确定原因)或某些最高有效位为 0 的正数(因为符号位是使其变大一位的位) )...关于如何解释这些情况,我可以获得任何提示或建议吗?
存储为单个字节,
正数的范围是
0x00
到 0x7F
0x80
到 0xFF
作为 2 字节,
正数的范围是
0x0000
到 0x7FFF
0x8000
到 0xFFFF
作为 4 字节,
正数的范围是
0x00000000
到 0x7FFFFFFF
0x80000000
到 0xFFFFFFFF
您可以使用如下函数来获取最小尺寸:
int getmin(int64_t i)
{
if(i == (int8_t)(i & 0xFF))
return 1;
if(i == (int16_t)(i & 0xFFFF))
return 2;
if(i == (int32_t)(i & 0xFFFFFFFF))
return 4;
return 8;
}
那么例如,当你看到
0x80
时,将其翻译为-128
。而 7F
会翻译为 127
,而 0x801
应翻译为正数。
请注意,这将非常困难且毫无意义,应该避免。这不适合以三字节存储数字,为此,您必须制定自己的格式。
以 x 字节2 的补码 可以存储的有符号数的范围是 -2^(8*x-1) 到 2^(8*x-1)-1。例如,1 个字节可以存储从 -128 到 127 的有符号整数。您的示例会错误地计算出只需要 1 个字节即可表示 128(如果我们谈论的是有符号数),因为右移 8 将等于 0,但是需要最后一个字节才能知道这不是负数。
对于处理负数,将其转换为正数并减一(因为负数可以存储额外的值)将允许您右移。
int i;
cin >> i;
unsigned bytes = 1;
unsigned max = 128;
if (i < 0) {
i = ~i; //-1*i - 1
}
while(max <= i) {
i >>= 8;
bytes++;
}
cout << bytes;
如果您使用 gcc,另一种选择是使用
__builtin_clz()
。这将返回前导零,然后您可以使用它来确定最小字节数。
#include <algorithm>
#include <bit>
constexpr unsigned int
byte_width(const size_t x)
{
// std::bit_width(0) returns 0, but we want it to be 1
const unsigned int w = std::max(std::bit_width(x), 1);
return (w / 8) + (w % 8 != 0);
}