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