简体   繁体   中英

How to check if int32_t number can fit in int8_t and int16_t?

I have a int32_t number and i need to check if will it fit in int8 and in16 but when i try:

    if (number ==(int32_t)((int8_t) number)) {
    printf("%s %d\n","8", number);
    
} else if (number ==(int32_t)((int16_t) number)){
    printf("%s %d\n","16", number);
    

Compiler says that first if statement is always true, but i don't know how to do it in other way, using only "==" and bits operations like << >>. and <stdint.h>.

As of C++ 20 you can do this:

std::in_range<std::int8_t>(-1)

see here

How to check if int32_t number can fit in int8_t and int16_t?

Like this:

extern std::int32_t value;

if (value <= std::numeric_limits<std::int8_t>::max()
 && value >= std::numeric_limits<std::int8_t>::min())

I expect std::int16_t case to be trivial based on this.


Since C++20, there is a simpler solution .

As mentioned in some of the comments, your original approach of just casting the values should work.

if (number == (int32_t)((int8_t) number)) {
  printf("%s %d\n","8", number);   
} else if (number == (int32_t)((int16_t) number)){
  printf("%s %d\n","16", number);
}

However, if you are required to do bit manipulations yourself (which is a bit unclear from your comments), then here are some other possible options.

Unsigned values:

You could just mask off the upper bits, by using the 'and' operation & with the maximum value for the smaller type.

If these numbers are both equal, it means the value would fit in the smaller type. If not, it means some of the upper bits were used (and got masked off) so the values would be unequal.

For instance, an 8-bit number maximum would be 11111111 or 255 .

#include <stdio.h>
#include <stdint.h>

if (number == (number & UINT8_MAX)) {  // Mask off the upper 24 bits
  printf("%s %d\n","8", number);
} else if (number == (number & UINT16_MAX)) {  // Mask off the upper 16 bits
  printf("%s %d\n","16", number);
}

Signed values:

For signed values, it's a bit trickier given your restrictions. Additionally, C/C++ do not appear to define a strict way of representing negative numbers, so it may vary by compiler. However, I believe my solution below should work for both one's complement and two's complement.

#include <stdio.h>
#include <stdint.h>

// Handle negative numbers by converting them to positive value.
// We will still need to handle the minimum (i.e. most negative) value, in
// case of two's complement.
int isNegative = ((originalNumber >> 31) != 0);
int positiveNumber = isNegative ? number * -1 : number;
    
if ((isNegative && (number == INT8_MIN)) ||
    (positiveNumber == (positiveNumber & INT8_MAX))) {
  printf("%s %d\n","8", number);
} else if ((isNegative && (number== INT16_MIN)) ||
           (positiveNumber == (positiveNumber & INT16_MAX))) {
  printf("%s %d\n","16", number);
}

If the number is positive, you can mask out the bottom 8 or 16 bits and compare.
If the number is negative, you have:

  • For numbers between -1 and -128 (fits in eight bits), the 25 top bits are all set.
  • From -129 and down, there is at least one zero in the top 25 bits.
  • For numbers between -1 and -32768 (fits in 16 bits), the 17 top bits are all set.
  • From -32769 and down, there is at least one zero in the top 17 bits.

So, something like this, perhaps:

char* answer[] = { "no", "yes" };
if (!(number >> 31))
{
    printf("Fits in eight: %s\n", answer[number == (number & 0xff)]);
    printf("Fits in 16: %s\n", answer[number == (number & 0xffff)]);
}
else
{
    printf("Fits in eight: %s\n", answer[(number >> 7) == 0x1ffffff]);
    printf("Fits in 16: %s\n", answer[(number >> 15) == 0x1ffff]);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM