如何确定宽度是“int”和“unsigned”两倍的整数类型?

中间乘法的值通常需要两倍的位数作为输入。

// Example int foo(int a, int b, int carry, int rem) { int2x c; // Some type that is twice as wide at `int` c = (int2x)a * b + carry; return (int) (c % rem); } 

考虑到填充的可能性(似乎限制了sizeof()有用性)和非2的补码整数(限制了位误),……

以下是否始终创建所需类型?
如果没有,如何编写至少一个合理的解决方案,即使不完全可移植?


 #include  #include  #if LONG_MAX/2/INT_MAX - 2 == INT_MAX typedef long int2x; typedef unsigned long unsigned2x; #elif LLONG_MAX/2/INT_MAX - 2 == INT_MAX typedef long long int2x; typedef unsigned long long unsigned2x; #elif INTMAX_MAX/2/INT_MAX - 2 == INT_MAX typedef intmax_t int2x; typedef uintmax_t unsigned2x; #else #error int2x/unsigned2x not available #endif 

[编辑]
Qualify:“always”,如果longlong longintmax_tintmax_t #error就可以了。
我想知道的是,如果longlong longintmax_t中至少有1个可以正常工作, int2x会被正确输入吗?

注意:上面假设xxx_MAX是2的奇数幂减1.可能是一个很好的假设? 以上工作至少有2个平台,但这不是一个很好的可移植性测试。

所有* _MAX常量都是(2^n)-1forms的假设是有效的。 请参见6.2.6类型表示 ,特别是6.2.6.2整数类型 ,其中无符号整数类型的表示和有符号整数类型的正值完全定义为纯二进制,因此产生的最大值小于1的幂二。

对于signed类型,最好只使用所考虑类型的值范围并进行比较。

首先,可以尝试计算INT_MAX*INTMAX+INT_MAX ,以便在表达式a*b+carry具有最大可能值。 通过转换为intmax_t似乎更合理的方法:

  #define MAX_EXPRESSION ((intmax_t) INT_MAX * INTMAX + INT_MAX) 

但是,如果MAX_EXPRESSION的真实数学值大于INTMAX_MAX ,我们就会遇到麻烦。 所以,让我们做一些数学来围绕这个问题。

设表示c = INT_MAXm = INTMAX_MAX 。 从数学上讲,我们想知道c*c+c <= m 。 这导致了我们的不等式: c <= (m - c) / c 。 由于除法是整数,结果会被截断,因此在上一次操作中会丢失精确的数学运算。 因此,我们必须写一个更精确的表达式,如下所示:`c <= floor((m - c)/ c)+ fractional_part_of((m - c)/ c)。

如果c > floor((m - c) / c) ,严格地说,那么c >= floor((m - c) / c) + 1 > (m - c) / c ,其中除法是在数学意义上的(精确小数)。 这给了我们c*c+c > m ,矛盾。 因此,我们在数学上再次得出结论c <= floor((m - c) / c)

这个表达式在C中更方便,因为m-c在使用intmax_t类型计算时会给出正确的值(换句话说:它不是超出范围的值)。 现在,除法(m - c) / c将给出一个intmax_t范围内的整数,虽然可能被截断,因为除法是整数。 实际上,它毫不犹豫地给了我们价值floor((m - c) / c

这个comparisson给出了true,那么我们可以说c*c+c可以在intmax_t的最大有符号整数类型中表示,即intmax_t 。 特别是:存在一个有符号整数类型,它能够表示系统中的值c*c+c

现在,在C代码中,我们可以写:

  #define c INT_MAX #define m INTMAX_MAX #if (c <= (m - c) / c) // There exists a signed type in your system // such that INT_MAX*INTMAX+INT_MAX is representable // as a value in that type. #else #error Sorry, the size of INT_MAX cannot be doubled... #endif 

一旦确定intmax_t完成了这项工作,你就可以开始搜索具有解决问题的最小等级的有符号整数类型:我们可以再次询问我们为intmax_t做的同样的问题,例如longlong long

  #include  #include  #define c INT_MAX #if (c <= (INTMAX_MAX - c) / c) #if (c <= (LLONG_MAX - c) / c) #if (c <= (LONG_MAX - c) / c) typedef long int2x; #else typedef long long int2x; #endif #else typedef intmax_t int2x; #endif #else #error Sorry, the size of type "int" cannot be doubled... #endif