【问题标题】:Multiplying int with long result c#将 int 与长结果 c# 相乘
【发布时间】:2015-03-25 04:26:10
【问题描述】:

想知道为什么。 C# .Net 3.5

int a = 256 * 1024 * 1024;
int b = 8;
long c = b * a;
Console.WriteLine(c);//<-- result is -2147483648 

这个减号是从哪里来的?

【问题讨论】:

  • 可能是int 溢出和垃圾值锥

标签: c# .net-3.5 int long-integer multiplication


【解决方案1】:

这个减号是从哪里来的?

从整数溢出。请注意,您的代码相当于:

int a = 256 * 1024 * 1024;
int b = 8;
int tmp = b * a;
long c = tmp;
Console.WriteLine(c);

我已经将乘法从分配给long 变量中分离出来,以强调它们确实是单独的操作——乘法是使用Int32 算术执行的,因为两个操作数都是Int32——事实上结果分配给Int64之后是无关紧要的。

如果您想在 64 位算术中执行乘法,您应该将操作数之一转换为 long(即Int64):

int a = 256 * 1024 * 1024;
int b = 8;
long c = b * (long) a;
Console.WriteLine(c); // 2147483648

(将哪个操作数转换为 long 并不重要 - 无论如何,另一个操作数将隐式转换为 long。)

【讨论】:

  • 我不确定 int 范围,我怀疑它可能会溢出
  • 我对 result 的值感到困惑,它与预期的值相同,但带有负号。如果我使用其他值,那就更清楚这是一个溢出问题。
【解决方案2】:

它将结果转换为 long 而不是操作,如果其中一个操作数很长,它可以工作这工作正常:

long a = 256L * 1024L * 1024L;
int b = 8;
long c = b * a;
Console.WriteLine(c);

就像这样:

int a = 256 * 1024 * 1024;
long b = 8L;
long c = b * a;
Console.WriteLine(c);

还有这个(这两个中只需要一个,但为了清楚起见,我做了两个):

int a = 256 * 1024 * 1024;
int b = 8;
long c = (long)b * (long)a;
Console.WriteLine(c);

【讨论】:

    【解决方案3】:

    int 支持的最大值是2147483647。预期结果2147483648 不适合此类型范围,因此发生溢出导致结果为负。

    请注意,long c = b * a; 语句转换为以下两个步骤:

    1. int 的值与ba 相乘。由于整数溢出,int 结果为负数。

    2. 将已经否定的结果转换为long

    在相乘之前尝试转换为long

    long c = b * (long) a;
    

    或将a 声明为long 类型:

    long a = 256L * 1024L * 1024L;
    

    【讨论】:

      【解决方案4】:

      因为b * a在赋值给long数据类型变量之前已经是溢出整数了。

      【讨论】:

        【解决方案5】:

        int 是一个 32 位 signed 值类型,这意味着最后一位用于指定数字是正数还是负数。

        int 的值范围从-21474836482147483647。这是

        1000 0000 0000 0000 0000 0000 0000 0000

        0111 1111 1111 1111 1111 1111 1111 1111

        二进制。现在:

        256 * 1024 * 1024 等于 268435456

        0001 0000 0000 0000 0000 0000 0000 0000二进制。

        268435456 * 8 等于 2147483648

        1000 0000 0000 0000 0000 0000 0000 0000

        由于该值仍然是int,因此循环回最大 数,因为如上所述,最后一位用于指定该数是正数还是负数。所以,2147483648 变成了-2147483648

        【讨论】:

          【解决方案6】:

          正如其他人所说,您应该将表达式中的一个操作数设为long 以产生long,但在您的情况下,所有操作数都是int,因此返回int

          您应该将其中一个转换为长:

          int a = 256 * 1024 * 1024;
          int b = 8;
          long c = (long)b * a;
          

          除法时也会发生同样的情况:

          int a=1, b=2;
          float c = a / b; //results in 0
          

          因此将操作数之一转换为结果类型:

          int a=1, b=2;
          float c = (float)a / b; //results in 0.5
          

          顺便说一句,还有用于检查算术溢出的 C# 指令:checked 关键字

          checked
          {
             int a = 256 * 1024 * 1024;
             int b = 8;
             long c = b * a; //this will throw System.OverflowException
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多