19

我想要一个四舍五入到最接近整数的方程的结果。例如

137 * (3/4) = 103

考虑以下不正确的代码。

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)
   );
4

12 回答 12

17

如上所述,您应该在除法之前进行乘法运算。无论如何,你可以只用除数来写你的表达式:

int height2 = (int)Math.Round(width2 * (height1 / (float)width1));
于 2008-11-18T15:50:29.513 回答
3
int height2 = (width2 * height1) / width1;
于 2008-11-18T15:40:45.570 回答
3

先做乘法(只要它们不太可能溢出),然后再做除法。

整数数学中的 3/4 == 0 (整数数学不会在除法时四舍五入,它会截断)。

如果您真的需要舍入,则必须使用定点、浮点或使用模数。

于 2008-11-18T15:45:00.007 回答
2

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

Math.round(myinteger * 0.75);

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

于 2011-03-15T21:51:53.323 回答
1

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

float width1 = 4;
float height1 = 3;

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

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

于 2008-11-19T02:23:15.633 回答
1

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

于 2009-01-24T19:53:51.203 回答
1

刚刚偶然发现这个问题。亚伦的回答对我来说似乎几乎是正确的。但我非常确定如果您的问题是“现实世界”问题,您需要指定中点舍入。所以我的答案,基于亚伦的代码,是

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();

有关详细信息,您可以查看这篇文章。

于 2013-09-06T14:11:27.967 回答
1

六年后(四舍五入),这是我的贡献——我很久以前就学会的一个小技巧,很惊讶没有其他人在这里提到过。

这个想法是通过在进行除法之前将除数的一半添加到分子来进行舍入。

    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);

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

于 2014-07-06T02:54:29.217 回答
0

对 Jeffery 消息的详细说明,因为您通常比溢出 32 位整数更有可能截断所需的小数(并且因为乘法和除法是可交换的),您通常应该在除法之前进行乘法运算。

于 2008-11-18T15:44:52.380 回答
0
int height2 = ((width2 * height1 * 10) + 5) / (width1 * 10);

在进行任何整数除法之前,请检查以确保除数不为零。另请注意,这假定为正商。如果为负数,则舍入需要为 -5,而不是 +5。

于 2008-11-19T02:09:00.810 回答
0

Convert 的转换总是四舍五入,所以:

int height2 = Convert.ToInt32(width2 * height1 / (double)width1);
于 2011-08-22T22:40:23.123 回答
0

如果最终除以偶数并且结果始终为正,则一种相当有效的方法是除以该值的一半,加一,再除以二。如果结果可能是负数,则应尽可能添加一个使一切为正数的量,进行计算,然后减去相应的量。

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

于 2013-11-02T06:11:58.513 回答