无符号 int 和双转换顺序



我对无符号的 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. 1:在下文中,(a2-a1)unsigned值为 4294967100 - 4294967290 mod 42949672964294967106
    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);
    
  2. 1:下面比较复杂。 a2-a1具有4294967106unsigned值。 此值强制转换为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,则结果至少是未指定的(并且可能是未定义的行为:我忘记了)。 这里可能就是这种情况。 实际上,这将在许多系统上生成负数,但相信这通常是一个坏主意。

然后将intunsigned算术转换为double,乘以 0.1,然后转换为相同kunsigned int算术模2^k(可能进行奇怪的四舍五入:在转换为无符号之前朝零?

没有理由认为这些会产生相同的价值。

最新更新