我对无符号的 int 和双转换顺序感到困惑。我认为在计算表达式时,中间类型是表示集基数最大的类型,但在代码中
unsigned int a1 = 4294967290, a2 = 4294967100;
unsigned int value1 = (a2 - a1) * double(0.1);
std::cout << value1 << std::endl;
unsigned int value2 = int(a2 - a1)* double(0.1);
std::cout << value2 << std::endl;
使用编译器编译时Microsoft我收到以下结果:
值 1 = 429496710值 2 = 4294967277
而我认为答案的直接类型应该是双倍的,因此值 1 和值 2 应该相等
我错在哪里?
-
1:在下文中,
(a2-a1)
的unsigned
值为4294967100 - 4294967290 mod 4294967296
或4294967106
。
2:它是由4294967296
修改的,因为在您的平台上,UINT_MAX
4294967295
。
3:4294967106 * 0.1
-->(double) 429496710.6
4:将(double) 429496710.6
分配给value1
会导致(unsigned) 429496710
。unsigned int value1 = (a2 - a1) * double(0.1);
-
1:下面比较复杂。
a2-a1
具有4294967106
的unsigned
值。 此值强制转换为int()
,并导致未指定/未定义的行为,如@Yakk建议的那样。 典型的结果是类型4294967106 - 4294967296
或-190
。
2:-190 * 0.1
-->(double) -19.0
3:将(double) -19.0
分配给value2
是一个问题,因为它是unsigned
的负数,再次遇到UB。
4:value2
被分配了(unsigned) 4294967277
的值,该值与平台上(int) -19
位模式相同。unsigned int value2 = int(a2 - a1)* double(0.1);
你减去两个unsigned int
。 这为某些k
(可能是 32 个)进行了算术模2^k
。
在一种情况下,您可以将其转换为 int
. 如果它大于 max int,则结果至少是未指定的(并且可能是未定义的行为:我忘记了)。 这里可能就是这种情况。 实际上,这将在许多系统上生成负数,但相信这通常是一个坏主意。
然后将int
或unsigned
算术转换为double
,乘以 0.1
,然后转换为相同k
的unsigned int
算术模2^k
(可能进行奇怪的四舍五入:在转换为无符号之前朝零?
没有理由认为这些会产生相同的价值。