How to determine how many bytes an integer needs?

前端 未结 22 1301
悲&欢浪女
悲&欢浪女 2020-12-13 02:13

I\'m looking for the most efficient way to calculate the minimum number of bytes needed to store an integer without losing precision.

e.g.

int: 10 = 1 byte
         


        
相关标签:
22条回答
  • 2020-12-13 03:05

    I think this is a portable implementation of the straightforward formula:

    #include <limits.h>
    #include <math.h>
    #include <stdio.h>
    
    int main(void) {
        int i;
        unsigned int values[] = {10, 257, 67898, 140000, INT_MAX, INT_MIN};
    
        for ( i = 0; i < sizeof(values)/sizeof(values[0]); ++i) {
            printf("%d needs %.0f bytes\n",
                    values[i],
                    1.0 + floor(log(values[i]) / (M_LN2 * CHAR_BIT))
                  );
        }
        return 0;
    }
    

    Output:

    10 needs 1 bytes
    257 needs 2 bytes
    67898 needs 3 bytes
    140000 needs 3 bytes
    2147483647 needs 4 bytes
    -2147483648 needs 4 bytes

    Whether and how much the lack of speed and the need to link floating point libraries depends on your needs.

    0 讨论(0)
  • 2020-12-13 03:06

    Assuming a byte is 8 bits, to represent an integer x you need [log2(x) / 8] + 1 bytes where [x] = floor(x).

    Ok, I see now that the byte sizes aren't necessarily a power of two. Consider the byte sizes b. The formula is still [log2(x) / b] + 1.

    Now, to calculate the log, either use lookup tables (best way speed-wise) or use binary search, which is also very fast for integers.

    0 讨论(0)
  • 2020-12-13 03:06

    I know this question didn't ask for this type of answer but for those looking for a solution using the smallest number of characters, this does the assignment to a length variable in 17 characters, or 25 including the declaration of the length variable.

    //Assuming v is the value that is being counted...
    int l=0;
    for(;v>>l*8;l++);
    
    0 讨论(0)
  • 2020-12-13 03:08

    The function to find the position of the first '1' bit from the most significant side (clz or bsr) is usually a simple CPU instruction (no need to mess with log2), so you could divide that by 8 to get the number of bytes needed. In gcc, there's __builtin_clz for this task:

    #include <limits.h>
    int bytes_needed(unsigned long long x) {
       int bits_needed = sizeof(x)*CHAR_BIT - __builtin_clzll(x);
       if (bits_needed == 0)
          return 1;
       else
          return (bits_needed + 7) / 8;
    }
    

    (On MSVC you would use the _BitScanReverse intrinsic.)

    0 讨论(0)
  • 2020-12-13 03:10

    Why not just use a 32-bit hash?


    That will work at near-top-speed everywhere.

    I'm rather confused as to why a large hash would even be wanted. If a 4-byte hash works, why not just use it always? Excepting cryptographic uses, who has hash tables with more then 232 buckets anyway?

    0 讨论(0)
  • 2020-12-13 03:10

    Why so complicated? Here's what I came up with:

    bytesNeeded = (numBits/8)+((numBits%8) != 0);

    Basically numBits divided by eight + 1 if there is a remainder.

    0 讨论(0)
提交回复
热议问题