C++ 如何便携式查找最小值(INT_MAX,abs(INT_min))?

C++ 如何便携式查找最小值(INT_MAX,abs(INT_min))?,c++,c,math,limits,C++,C,Math,Limits,如何便携式查找INT\u MAX和abs(INT\u MIN)中的最小值?(这是INT\u MIN的数学绝对值,不是对abs函数的调用。) 在大多数系统中,它应该与INT\u MAX相同,但我正在寻找一种更便携的方式。在大多数系统中,abs(INT\u MIN)没有定义。例如,在典型的32位计算机上,INT_MAX=2^31-1,INT_MIN=-2^31,abs(INT_MIN)不能为2^31 abs(INT\u MIN)将调用未定义的行为。标准说 7.22.6.1abs、labs和LLAB功

如何便携式查找
INT\u MAX
和abs(
INT\u MIN
)中的最小值?(这是
INT\u MIN
的数学绝对值,不是对
abs
函数的调用。)

在大多数系统中,它应该与
INT\u MAX
相同,但我正在寻找一种更便携的方式。

在大多数系统中,abs(INT\u MIN)没有定义。例如,在典型的32位计算机上,INT_MAX=2^31-1,INT_MIN=-2^31,abs(INT_MIN)不能为2^31

abs(INT\u MIN)
将调用未定义的行为。标准说

7.22.6.1
abs
labs
LLAB
功能:
abs
labs
llabs
函数计算整数
j
的绝对值。如果无法表示结果,则行为未定义

试试这个:
INT\u MIN
转换为
unsignrd INT
。由于-ve数字不能表示为
无符号整数
int\u MAX
将转换为
UINT\u MAX+1+int\u MIN

#include <stdio.h>
#include <stdlib.h>

unsigned min(unsigned a, unsigned b)
{
    return a < b ? a : b;
}

int main(void)
{
    printf("%u\n", min(INT_MAX, INT_MIN));
}  
#包括
#包括
无符号最小值(无符号a、无符号b)
{
返回a
INT\u MAX+INT\u MIN<0?最大整数:-最小整数

编辑以添加解释:当然困难在于
-INT\u MIN
abs(INT\u MIN)
如果
-INT\u MIN
太大而无法装入
INT
中,则将无法定义。因此,我们需要某种方法来检查情况是否如此。条件
INT\u MAX+INT\u MIN<0
测试
-INT\u MIN
是否大于
INT\u MAX
。如果是,则
INT_MAX
是两个绝对值中的较小值。如果不是,则<代码> INTXMAX是两个绝对值中较大的,并且> INTHINMIN是正确答案。据我所知,

<代码> -INTMAX 在所有C和C++方言中都可以表示为<代码> INT/COD>。因此:

-INT_MAX <= INT_MIN ? -INT_MIN : INT_MAX

C99及以上版本中的
-INT\u MAX,
INT\u MAX

引用规范:

对于有符号整数类型,对象表示的位应分为三个 组:值位、填充位和符号位。不需要任何填充位; 有符号字符不得有任何填充位。应正好有一个符号位。 作为值位的每个位应具有与对象中相同位相同的值 对应无符号类型的表示(如果有符号类型中有M个值位 在无符号类型中键入和N,然后是M≤ N) 。如果符号位为零,则不应影响 结果值。如果符号位为1,则应在其中一个 以下方法:

  • 符号位为0的对应值为负数(符号和幅值)
  • 符号位具有该值−(2^M)(二者的补充)
  • 符号位具有该值−(2^M− 1) (一人之补)
(的第6.2.6.2节)

虽然
INT\u MIN
的典型值为-2147483648,
INT\u MAX
的典型值为2147483647,但本标准不保证。TL;DR:您搜索的值是一致性实现中的
INT\u MAX
。但是计算
min(INT\u MAX,abs(INT\u min))
是不可移植的


INT\u MIN
INT\u MAX

<代码> In MIX和 InthMax 由附录E(实现限制)1定义(C标准,C++继承了这一类):

标题内容按字母顺序如下所示 秩序。所示最小震级应替换为 实现定义的具有相同符号的震级。数值应为: 所有表达式都是常量表达式,适合在#if预处理中使用 指令。5.2.4.2.1中进一步描述了这些部件

[……]

#定义INT_MAX+32767

#定义整数最小值-32767

[……]

本标准要求类型
int
为整数类型,可表示范围
[int\u MIN,int\u MAX]
(第5.2.4.2.1节)

然后是6.2.6.2。(整数类型,也是C标准的一部分),并进一步将其限制为我们所知的2或1的补码:

对于有符号整数类型,对象表示的位应分为三个 组:值位、填充位和符号位。不需要任何填充位; 有符号字符不得有任何填充位。应正好有一个符号位。 作为值位的每个位应具有与对象中相同位相同的值 对应无符号类型的表示(如果有符号类型中有M个值位 在无符号类型中键入和N,然后是M≤ N) 。如果符号位为零,则不应影响结果值。如果符号位为1,则应在其中一个 以下方法:

-符号位为0的对应值为负数(符号和幅值)

-符号位具有该值−(2M)(二者的补充)

-符号位具有该值−(2米− 1) (一人之补)

第6.2.6.2节。将有符号整数类型的值表示与其无符号同级的值表示相关联也非常重要

这意味着,您可以得到范围
[-(2^n-1)、(2^n-1)]
[-2^n,(2^n-1)]
,其中
n
通常是15或31

对有符号整数类型的操作 现在来看第二件事:对有符号整数类型的操作,其结果值不在
[INT\u MIN,INT\u MAX]
范围内,行为未定义。这是在C++中明确规定的第5/4段:

如果在表达式求值期间,结果不是数学
-INT_MAX <= INT_MIN ? -INT_MIN : INT_MAX
`INT_MAX + INT_MIN`  |  value of -INT_MIN    | value of -INT_MAX 
------------------------------------------------------------------
         < 0         |  undefined            | -INT_MAX
         = 0         |  INT_MAX = -INT_MIN   | -INT_MAX = INT_MIN
         > 0         |  cannot occur according to 6.2.6.2. of the C standard
if ( INT_MAX + INT_MIN == 0 )
{
    return INT_MAX; // or -INT_MIN, it doesn't matter
}
else if ( INT_MAX + INT_MIN < 0 )
{
    return INT_MAX; // INT_MAX is smaller, -INT_MIN cannot be represented.
}
else // ( INT_MAX + INT_MIN > 0 )
{
    return -INT_MIN; // -INT_MIN is actually smaller than INT_MAX, may not occur in a conforming implementation.
}
return (INT_MAX + INT_MIN <= 0) ? INT_MAX : -INT_MIN;
assert(INT_MAX + INT_MIN <= 0);
return INT_MAX;
static_assert(INT_MAX + INT_MIN <= 0, "non-conforming implementation");
return INT_MAX;