C#:我如何对整数进行简单的四舍五入运算?

C#:我如何对整数进行简单的四舍五入运算?,c#,math,rounding,C#,Math,Rounding,我想要一个方程式的结果四舍五入到最接近的整数。 e、 g 考虑以下错误代码 int width1 = 4; int height1 = 3; int width2 = 137; int height2 = width2 * (height1 / width1); 在C#中执行“整数”数学的正确方法是什么 我真的必须做: int height2 = (int)Math.Round( (float)width2 * ((float)height1 / (float)width1)

我想要一个方程式的结果四舍五入到最接近的整数。 e、 g

考虑以下错误代码

int width1 = 4;
int height1 = 3;

int width2 = 137;
int height2 = width2 * (height1 / width1);
在C#中执行“整数”数学的正确方法是什么

我真的必须做:

int height2 = (int)Math.Round(
      (float)width2 * ((float)height1 / (float)width1)
   );

关于Jeffery的信息,由于通常情况下,截断所需小数的几率比溢出32位整数的几率要大(而且因为乘法和除法是可交换的),所以通常应该先乘法再除法。

先乘法(只要它们不太可能溢出)第二组

整数数学中的3/4==0(整数数学在除法时不舍入,而是截断)


如果你真的需要舍入,你要么用定点,要么用浮点,要么用模数。

如上所述,你应该在除法之前先做乘法。 无论如何,您可以只使用除数来编写表达式:

int height2 = (int)Math.Round(width2 * (height1 / (float)width1));
在进行任何整数除法之前,请检查除数是否为零。
还要注意的是,这假设了正商。如果为负值,舍入值需要为-5,而不是+5

我将通过添加零行代码来修复不正确的代码:

float width1 = 4;
float height1 = 3;

float width2 = 137;
float height2 = width2 * (height1 / width1);

对于可能包含小数的变量,应该使用浮点。这包括根据比率计算的高度。如果有问题,您可以稍后再转换为int。

永远不要转换为float,它的精度甚至低于32位整数。如果要使用浮点,请始终使用double而不是float。

我认为这是最优雅的方法:

Math.round(myinteger * 0.75);

使用0.75而不是3/4将隐式地将其转换为双精度/浮点型,为什么不使用为此提供的默认函数?

Convert的转换总是四舍五入,因此:

int height2 = Convert.ToInt32(width2 * height1 / (double)width1);

我偶然发现了这个问题。亚伦的回答在我看来几乎是对的。但我非常确定,如果您的问题是“真实世界”的问题,则需要指定中点舍入。根据亚伦的密码,我的答案是

int height2 = (int)Math.Round(width2 * (height1 / (float)width1),MidpointRounding.AwayFromZero);
要查看差异,请在控制台中运行该代码

    Console.WriteLine((int)Math.Round(0.5));
    Console.WriteLine((int)Math.Round(1.5));
    Console.WriteLine((int)Math.Round(2.5));
    Console.WriteLine((int)Math.Round(3.5));
    Console.WriteLine((int)Math.Round(0.5, MidpointRounding.AwayFromZero));
    Console.WriteLine((int)Math.Round(1.5, MidpointRounding.AwayFromZero));
    Console.WriteLine((int)Math.Round(2.5, MidpointRounding.AwayFromZero));
    Console.WriteLine((int)Math.Round(3.5, MidpointRounding.AwayFromZero));
    Console.ReadLine();

有关详细信息,请参阅文章。

如果最终除法为偶数,且结果始终为正数,则合理有效的方法是将该值除以一半,再加上一,再除以二。如果结果可能是负数,如果可能的话,你应该加上一个使一切都是正数的量,进行计算,然后减去相应的量

如果最后的除法是奇数,则将分子和分母都乘以2,然后按上述步骤进行。例如,要计算*5/7,四舍五入,请计算
(a*10+1)>>1
。需要注意的一点是,您可能需要将值扩展到更大的数字类型,以避免溢出,或者,如果不可能的话,将分割细分为多个部分。例如,要计算*14/15,可以计算((a*4/3*7)/5+1)/2。如果a太大,该计算仍可能溢出,但允许的范围将是未在另一次除法之前进行除法3计算时的三倍。请注意,细分操作将使舍入稍微不精确,但在许多情况下仍然足够接近。

六年后(舍入),这里是我的贡献-这是我很久以前学会的一个小技巧,令人惊讶的是,这里没有人提到

其思想是在除法之前,先将除数的一半加到分子上,进行四舍五入

    int height2 = (width2 * height1 + width1 / 2) / width1;
事实上,我不建议在除数是变量的情况下,比如OP。相反,最好使用Math.Round(),因为它更容易理解

但在除数是常数的情况下,我会使用这个技巧。所以不是

    int height2 = width2 * height1 / 4;  // No rounding
我会用

    int height2 = (width2 * height1 + 2) / 4;
这里有一个更典型的例子

  private static Size ResizeWithPercentage(Size oldSize, int resizePercentage)
  {
     return new Size((oldSize.Width * resizePercentage + 50) / 100, 
                     (oldSize.Height * resizePercentage + 50) / 100);
  }
另一种可能是将这个技巧与dongilmore和supercat提到的想法结合起来,即不必指定或隐含除法,而是可以将分子和分母都乘以2

    int height2 = (width2 * height1 * 2 + width1) / (width1 * 2);

在除数是或可能是奇数的情况下,这会给出更好的答案。

原始值是整数,只能包含整数。接下来的问题是如何与他们进行数学运算。如果我在做浮点运算,我会问这个问题。(事实上,不是真的,因为FP math不会有问题)既然我将四舍五入到一个32位整数,那么double在小数点后的第8位有一个有意义的数字,而float没有关系吗?也就是说,79.99999999比79.99999999999差吗?是的。32位整数约为9位,但32位浮点仅约为7位。请记住:偶尔给出轻微错误答案的代码是最糟糕的错误,比总是得到完全错误的答案更糟糕!你能举出一个例子,把一个数学转换成32位整数会给出错误的答案,而把两个数学转换成32位整数是正确的吗?@IanBoyd:你试过了吗?除非您使用的语言将
float
升级为
double
,否则16777216.0f+1.0f将生成16777216.0f,因为在16777216.0f和16777218.0f之间没有
float
值,这没有帮助。仍然应该是“int-height2=((width2*height1*10)+width1*5)/(width1*10);”令人遗憾的是,一年后,我仍然必须回到这个问题上来,以了解如何用C#做数学。在delphi中,我只需输入“137*3/4”就可以了。但不是C#,C#强迫你在做你想做的事情之前先向编译神祈祷。一年后见之明的好处是:你能解释为什么我应该先做乘法吗?乘法最后会把数字移到左边。分裂向右移。如果乘法不会导致溢出,则不会丢失精度。除法很可能会丢失精度,因为您将丢失位(如果除以2,则丢失1位,如果除以16,则丢失4位,以此类推)
    int height2 = (width2 * height1 + 2) / 4;
  private static Size ResizeWithPercentage(Size oldSize, int resizePercentage)
  {
     return new Size((oldSize.Width * resizePercentage + 50) / 100, 
                     (oldSize.Height * resizePercentage + 50) / 100);
  }
    int height2 = (width2 * height1 * 2 + width1) / (width1 * 2);