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

发布于 2024-07-08 21:48:34 字数 391 浏览 7 评论 0原文

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

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

i want the result of an equation rounded to the nearest integer.
e.g.

137 * (3/4) = 103

Consider the following incorrect code.

int width1 = 4;
int height1 = 3;

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

What is the proper way to perform "integer" math in C#?

Do i really have to do:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

被你宠の有点坏 2024-07-15 21:48:35

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

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

As said above, you should do the multiplication before the division.
Anyway you could write your expression with casting only the divisor:

int height2 = (int)Math.Round(width2 * (height1 / (float)width1));
無處可尋 2024-07-15 21:48:35
int height2 = (width2 * height1) / width1;
int height2 = (width2 * height1) / width1;
千柳 2024-07-15 21:48:35

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

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

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

Do multiplication first (as long as they're not likely to overflow) and division second.

3/4 == 0 in integer math (integer math doesn't round on division, it truncates).

If you really need rounding, you have to either work in fixed point, floating point, or play around with the modulus.

旧人 2024-07-15 21:48:35

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

Math.round(myinteger * 0.75);

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

I think this is the most elegant way to do this:

Math.round(myinteger * 0.75);

Using 0.75 instead of 3/4 will implicitly cast it to an double/float and why not use the default functions that are provided for this?

二手情话 2024-07-15 21:48:35

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

float width1 = 4;
float height1 = 3;

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

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

I will fix the incorrect code by adding zero lines of code:

float width1 = 4;
float height1 = 3;

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

You should use floats for variables that can possibly contain decimals. This includes heights calculated from ratios. You can always cast to int later if that is a problem.

十雾 2024-07-15 21:48:35

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

Never cast to float, it has even less precision than a 32-bit integer. If you're going to use floating point, always use double instead of float.

黯然 2024-07-15 21:48:35

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

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

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

Just stumbled upon this question. Aaron's answer seems almost right to me. But I'm very sure you need to specify midpointrounding if your problem is a "real world" problem. So my answer, based on Aaron's code, is

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

To see the difference run that code in console

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

For details you may look at this article.

放飞的风筝 2024-07-15 21:48:35

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

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

    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,而不是除以指定或隐含的 2。

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

当除数是或可能是奇数时,这会给出更好的答案。

Six years (rounded) later, here's my contribution - a little trick I learned long ago, and am surprised that nobody else has mentioned here.

The idea is to do rounding by adding half of the divisor to the numerator before doing the division.

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

In reality I wouldn't necessarily recommend doing that in cases, like the OP's, where the divisor is a variable. Instead it may be better to use Math.Round(), as it's much easier to understand.

But in cases where the divisor is a constant I do use this trick. So instead of

    int height2 = width2 * height1 / 4;  // No rounding

I'd use

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

Here's a more typical example

  private static Size ResizeWithPercentage(Size oldSize, int resizePercentage)
  {
     return new Size((oldSize.Width * resizePercentage + 50) / 100, 
                     (oldSize.Height * resizePercentage + 50) / 100);
  }

Another possibility is to combine this trick with the idea mentioned by dongilmore and supercat that instead of having a division by two specified or implied, you can multiply both the numerator and denominator by two.

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

This gives better answers in cases where the divisor is, or may be, an odd number.

心意如水 2024-07-15 21:48:35

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

The elaborate on Jeffery's message, since you generally a better chance of truncated needed decimals than you have of overflowing a 32-bit integer (and because multiplication & division is commutative), you should generally do multiplication before division.

怪我入戏太深 2024-07-15 21:48:35

Convert 的转换总是四舍五入:

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

Convert's conversions always round so:

int height2 = Convert.ToInt32(width2 * height1 / (double)width1);
风轻花落早 2024-07-15 21:48:35
int height2 = ((width2 * height1 * 10) + 5) / (width1 * 10);

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

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

Prior to any integer division, check to make certain the divisor is not zero.
Also note this assumes positive quotient. If negative, roundoff needs to be -5, not +5.

述情 2024-07-15 21:48:35

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

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

A reasonably effective approach if the final division will be by an even number and the result will always be positive is to divide by half that value, add one, and divide by two. If the result may be negative, you should if possible add an amount that will make everything be positive, do the computation, and then subtract a corresponding amount afterward.

If the final division will be by an odd number, multiply both numerator and denominator by 2, then proceed as above. For example, to compute a*5/7, rounded, compute (a*10+1)>>1. The one thing to watch out for is that you may need to extend your values to a larger numeric type to avoid overflow or, if that isn't possible, subdivide the division into pieces. For example, to compute a*14/15, you might compute ((a*4/3*7)/5+1)/2. That computation may still overflow if a is too big, but the allowable range will be three times as big as if it was evaluated without doing the divide by 3 before the other division. Note that subdividing the operation will make the rounding slightly less precise, but still close enough for many purposes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文