首页 文章

返回未知int类型的范围

提问于
浏览
1

我被分配了一个问题,其中某人可能放入任何类型的有符号/无符号整数,并且两个函数必须使用按位运算等返回相应的最小值和最大值 .

我正在尝试调整我对二进制补码的了解 - 范围由 - (2n-1)到(2n-1 - 1)定义为有符号,0到(2n - 1)为无符号值 .

但是,当我使用以下方法进行无符号时:

void create_minmax_unsigned() {
    unknownun exponent = (sizeof(unknownun) * 8) - 1;
    unknownun max = (1 << exponent) - 1;
    printf("The max is %d", max);
}

并签署:

void create_minmax_signed() {
    unknowns exponent = (sizeof(unknowns) * 8) - 1;
    unknowns min = ((1 << exponent) + 1) - 1;
    unknowns max = (1 << exponent) - 1;
}

这种方法适用于char(un / s),short(un / s),int(un / s),long(un / s)但不长,即64位 .

编辑:它实际上返回所有int类型的正确位数 . 但是,对于 long long ,它没有显示正确的范围 .

2 回答

  • 0

    long long 计算失败的原因是,分配的RHS计算为 int ,并且您试图按 int 的值过大 .

    这个spiel逐步发展答案 - 只有最终的代码才真正可行 . 早期版本有各种问题需要解决,一次只能解决一个问题 .

    您需要将RHS强制转换为指定的类型:

    void create_minmax_unsigned() {
        unknownun exponent = (sizeof(unknownun) * 8) - 1;
        unknownun max = ((unknownun)1 << exponent) - 1;
        printf("The max is %d", max);
    }
    
    void create_minmax_signed() {
        unknowns exponent = (sizeof(unknowns) * 8) - 1;
        unknowns min = (((unknowns)1 << exponent) + 1) - 1;
        unknowns max = ((unknowns)1 << exponent) - 1;
    }
    

    返回多个值时遇到问题 . 使用 <inttypes.h>intmax_tuintmax_t 强制转换可以使您的打印代码更加强大:

    void create_minmax_unsigned() {
        unknownun exponent = (sizeof(unknownun) * 8) - 1;
        unknownun max = ((unknownun)1 << exponent) - 1;
        printf("The max is %" PRIuMAX, (uintmax_t)max);
    }
    
    void create_minmax_signed() {
        unknowns exponent = (sizeof(unknowns) * 8) - 1;
        unknowns min = (((unknowns)1 << exponent) + 1) - 1;
        unknowns max = ((unknowns)1 << exponent) - 1;
        printf("The max is %" PRIdMAX, (intmax_t)max);
        printf("The min is %" PRIdMAX, (intmax_t)min);
    }
    

    解决溢出问题

    到目前为止,这使您的计算基本保持不变;它只是确保值的类型正确 . 但是,您的计算容易受到数字溢出的影响,这可能(非常)非常糟糕 - 它会导致带符号整数类型的未定义行为和无符号类型的错误答案 .

    对于无法使用较大类型来覆盖罪孽的无符号类型,需要仔细创建2n-1,因为 2<sup>n</sup> 大于可以存储的值,因此它看起来像0.当你减去1时,你会得到正确的答案,但你真的不需要转移/取幂 .

    void create_minmax_unsigned() {
        unknownun max = (unknownun)0 - 1;
        printf("The max is %" PRIuMAX, (uintmax_t)max);
    }
    

    对于签名类型,您不能使用2n-1 - 1,因为无法表示2n-1 . 但是,您可以使用2 *(2n-2 - 1)1 . 负限制是减去一个值的否定值,导致:


    未经测试的代码(错误):

    void create_minmax_signed() {
        unknowns exponent = (sizeof(unknowns) * 8) - 2;
        unknowns max = 2 * ((unknowns)1 << exponent) + 1;
        unknowns min = -max - 1;
        printf("The max is %" PRIdMAX, (intmax_t)max);
        printf("The min is %" PRIdMAX, (intmax_t)min);
    }
    

    经测试的代码(不是那么多错误):

    #include <inttypes.h>
    #include <stdio.h>
    
    typedef signed long long unknowns;
    void create_minmax_signed(void);
    
    void create_minmax_signed(void)
    {
        unknowns exponent = (sizeof(unknowns) * 8) - 2;
        unknowns max = 2 * (((unknowns)1 << exponent) - 1) + 1;
        unknowns min = -max - 1;
        printf("The max is %+" PRIdMAX "\n", (intmax_t)max);
        printf("The min is %+" PRIdMAX "\n", (intmax_t)min);
    }
    
    int main(void)
    {
      create_minmax_signed();
      return 0;
    }
    

    汇编:

    /usr/bin/gcc -g -O3 -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -Wold-style-declaration -Werror  mnx.c -o mnx
    

    样品运行:

    $ ./mnx
    The max is +9223372036854775807
    The min is -9223372036854775808
    $
    
  • 0

    你不能只移动 1 << (sizeof(signed type)*CHAR_BIT-1) ,因为那是未定义的行为(如果 sizeof(signed type) >= sizeof(int) ) . 那么 (x+1)-1 是什么? (提示: x ,除非 x 是INT_MAX,在这种情况下,'s undefined). So that doesn' t会得到一个负数,是吗?

相关问题