找到你要的答案

Q:Two values in one byte

Q:一个字节中的两个值

In a single nibble (0-F) I can store one number from 0 to 15. In one byte, I can store a single number from 0 to 255 (00 - FF). Can I use a byte (00-FF) to store two different numbers each in the range 0-127 (00 - 7F)?

In a single nibble (0-F) I can store one number from 0 to 15. In one byte, I can store a single number from 0 to 255 (00 - FF). Can I use a byte (00-FF) to store two different numbers each in the range 0-127 (00 - 7F)?

answer1: 回答1:

The answer to your question is NO. You can split a single byte into two numbers, but the sum of the bits in the two numbers must be <= 8. Since, the range 0-127 requires 7 bits, the other number in the byte can only be 1 bit, i.e. 0-1.

你的问题的答案是否定的。你可以把一个字节分成两个数字,但这两个数字中的位的总和必须是。因为,范围中需要7位的字节数,其他的只能是1位,即0-1。

answer2: 回答2:

For obvious cardinality reasons, you cannot store two small integers in the 0 ... 127 range in one byte of 0 ... 255 range. In other words the cartesian product [0;127]×[0;127] has 214 elements which is bigger than 28 (the cardinal of the [0;255] interval, for bytes)

(If you can afford losing precision - which you didn't tell - you could, e.g. by storing only the highest bits ...)

Perhaps your question is: could I store two small integers from [0;15] in a byte? Then of course you could:

typedef unsigned unibble_t; // unsigned nibble in [0;15]
uint8_t make_from_two_nibbles(unibble_t l, unibble_t r) {
  assert(l<=15);
  assert(r<=15);
  return (l<<4) | r;
}

unibble_t left_nible (uint8_t x) { return x >> 4; }
unibble_t right_nibble (uint8_t) { return x & 0xf; }

But I don't think you always should do that. First, you might use bit fields in struct. Then (and most importantly) dealing with nibbles that way might be more inefficient and make less readable code than using bytes.

And updating a single nibble, e.g. with

void update_left_nibble (uint8_t*p, unibble_t l) {
  assert (p);
  assert (l<=15);
  *p = ((l<<4) | ((*p) & 0xf));

}

is sometimes expensive (it involves a memory load and a memory store, so uses the CPU cache and cache coherence machinery), and most importantly is generally a non-atomic operation (what would happen if two different threads are calling simultaneously update_left_nibble on the same address p -i.e. with pointer aliasing- is undefined behavior).

As a rule of thumb, avoid packing more than one data item in a byte unless you are sure it is worthwhile (e.g. you have a billion of such data items).

明显的基数的原因,你不能在0店两小整数…127范围在一个字节的0…255范围。换句话说,笛卡尔积[ 0;127 ]×0;127 ]有214个元素,大于28(基数为[ 0 ]区间,字节)

(如果你能失去精度-你没有告诉-你可以,例如存储只有最高的位…)

也许你的问题是:我可以存储两个小整数[ 0;15 ]在一个字节?那么你当然可以:

typedef unsigned unibble_t; // unsigned nibble in [0;15]
uint8_t make_from_two_nibbles(unibble_t l, unibble_t r) {
  assert(l<=15);
  assert(r<=15);
  return (l<<4) | r;
}

unibble_t left_nible (uint8_t x) { return x >> 4; }
unibble_t right_nibble (uint8_t) { return x & 0xf; }

但我不认为你总是应该这样做。首先,你可能在使用位域结构。然后(最重要的)处理啃方法可能是更有效率和使不可读的代码比使用字节。

更新一个单一的蚕食,例如

void update_left_nibble (uint8_t*p, unibble_t l) {
  assert (p);
  assert (l<=15);
  *p = ((l<<4) | ((*p) & 0xf));

}

有时是昂贵的(它涉及到内存加载和存储,所以使用CPU缓存和缓存一致性机械),最重要的是一般的非原子操作(什么如果两个不同的线程调用同时update_left_nibble在同一地址的P -即指针别名发生未定义行为)。

作为一个经验法则,避免在一个字节中填充多个数据项,除非你确信它是值得的(例如你有十亿这样的数据项)。

answer3: 回答3:

One byte is not enough for two values in 0…127, because each of those values needs log2(128) = 7 bits, for a total of 14, but a byte is only 8 bits.

You can declare variables with bit-packed storage using the C and C++ bitfield syntax:

struct packed_values {
    uint8_t first : 7;
    uint8_t second : 7;
    uint8_t third : 2;
};

In this example, sizeof(packed_values) should equal 2 because only 16 bits were used, despite having three fields.

This is simpler than using bitwise arithmetic with << and & operators, but it's still not quite the same as ordinary variables: bit-fields have no addresses, so you can't have a pointer (or C++ reference) to one.

一个字节不够0…两值127,因为每个人的价值观需要log2(128)= 7位,共计14个,但只有8位字节。

你可以声明变量的位填充存储使用C和C++位语法:

struct packed_values {
    uint8_t first : 7;
    uint8_t second : 7;
    uint8_t third : 2;
};

在这个例子中,sizeof(packed_values)应该等于2,因为只有16位,尽管有三场。

这比使用按位运算简单<;<;和&;运营商,但它仍然是不太一样的普通变量:位域没有地址,所以你不能有一个指针(或C++参考)一。

answer4: 回答4:

Can I use a byte to store two numbers in the range 0-127?

Of course you can:

uint8_t storeTwoNumbers(unsigned a, unsigned b) {
    return ((a >> 4) & 0x0f) | (b & 0xf0);
}

uint8_t retrieveTwoNumbers(uint8_t byte, unsigned *a, unsigned *b) {
    *b = byte & 0xf0;
    *a = (byte & 0x0f) << 4;
}

Numbers are still in range 0...127 (0...255, actually). You just loose some precision, similar to floating point types. Their values increment in steps of 16.

我可以用一个字节来存储两个数字范围中?

你当然可以:

uint8_t storeTwoNumbers(unsigned a, unsigned b) {
    return ((a >> 4) & 0x0f) | (b & 0xf0);
}

uint8_t retrieveTwoNumbers(uint8_t byte, unsigned *a, unsigned *b) {
    *b = byte & 0xf0;
    *a = (byte & 0x0f) << 4;
}

数字仍在范围0…127(0……,实际上,255)。你只是失去一些精度,类似浮点类型。它们的值增量在步骤16。

answer5: 回答5:

You can store two data in range 0-15 in a single byte, but you should not (one var = one data is a better design).

If you must, you can use bit-masks and bit-shifts to access to the two data in your variable.

uint8_t var; /* range 0-255 */

data1 = (var & 0x0F);      /* range 0-15 */
data2 = (var & 0xF0) >> 4; /* range 0-15 */

你可以存储两个数据范围0-15在单字节,但你不应该(一个var =一个数据是一个更好的设计)。

如果必须,可以使用位掩码和位移来访问变量中的两个数据。

uint8_t var; /* range 0-255 */

data1 = (var & 0x0F);      /* range 0-15 */
data2 = (var & 0xF0) >> 4; /* range 0-15 */
c++  c  hex  bit-manipulation