簡體   English   中英

C#:如何使用舍入對整數進行簡單的數學運算?

[英]C#: How do I do simple math, with rounding, on integers?

我希望方程的結果四舍五入到最接近的整數。 例如

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

如上所述,你應該在除法之前進行乘法運算。 無論如何,你可以只使用除數來編寫你的表達式:

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

首先進行乘法(只要它們不可能溢出)和第二次除法。

整數數學中的3/4 == 0(整數數學不會在除法上舍入,它會截斷)。

如果你真的需要舍入,你必須在固定點,浮點或模數周圍工作。

我認為這是最優雅的方式:

Math.round(myinteger * 0.75);

使用0.75而不是3/4將隱式地將其轉換為double / float,為什么不使用為此提供的默認函數?

只是偶然發現了這個問題。 亞倫的回答對我來說似乎是對的。 但我非常確定如果您的問題是“現實世界”問題,則需要指定midpointrounding。 所以根據Aaron的代碼我的回答是

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

有關詳情可看文章。

六年(四舍五入)之后,這是我的貢獻 - 我很久以前學到的一個小技巧,並且很驚訝沒有其他人在這里提到過。

這個想法是在進行除法之前通過將一半除數加到分子來進行舍入。

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

在除數是或可能是奇數的情況下,這給出了更好的答案。

我將通過添加零行代碼來修復錯誤的代碼:

float width1 = 4;
float height1 = 3;

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

您應該對可能包含小數的變量使用浮點數。 這包括根據比率計算的高度。 如果這是一個問題,您可以隨后轉換為int。

從不轉換為浮點數,它的精度甚至低於32位整數。 如果您要使用浮點數,請始終使用double而不是float。

一個合理有效的方法,如果最終除法將是偶數,結果總是正數,則除以該值的一半,加1,除以2。 如果結果可能是負數,則應盡可能添加一個使所有內容都為正的量,進行計算,然后再減去相應的量。

如果最終除法是奇數,則將分子和分母乘以2,然后按上述步驟進行。 例如,要計算* 5/7,舍入,計算(a*10+1)>>1 需要注意的一件事是,您可能需要將值擴展為更大的數值類型以避免溢出,或者如果不可能,則將除法細分為多個部分。 例如,要計算* 14/15,您可以計算((a * 4/3 * 7)/ 5 + 1)/ 2。 如果a太大,那么該計算可能仍會溢出,但允許范圍將是在沒有在另一個除法之前除以3的情況下進行評估的三倍。 請注意,細分操作會使舍入略微精確,但仍然足夠接近以達到很多目的。

詳細說明了Jeffery的消息,因為你通常比截斷32位整數(並且因為乘法和除法是可交換的)更有可能截斷所需的小數,你通常應該在除法之前進行乘法運算。

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

在進行任何整數除法之前,請檢查以確定除數不為零。 另請注意,這假定為正商。 如果是負數,則舍入需要為-5,而不是+5。

轉換的轉換總是如此:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM