如何舍入到最接近的整数?

Álv*_*cía 43 c# algorithm math rounding

我的最后一个目标是始终舍入到最接近的偶数.

例如,1122.5196我想要的数字作为结果1122.我试过这个选项:

Math.Round(1122.5196d, 0, MidpointRounding.ToEven);       // result 1123
Math.Round(1122.5196d, 0, MidpointRounding.AwayFromZero); // result 1123
Run Code Online (Sandbox Code Playgroud)

最后,我想得到它总是最近的偶数整数.例如:

  • 1122.51 --> 1122
  • 1122.9 --> 1122(因为最近的int是1123但它是奇数,且1122接近1124)
  • 1123.0 --> 1124(下一个偶数值,下一个更高的偶数值)

我只使用正数.

等等.

有一些方法可以做到这一点,或者我应该实现自己的方法?

Dmi*_*nko 64

试试这个(让我们使用Math.RoundMidpointRounding.AwayFromZero为了获得" 下一个甚至价值",但比例 - 2因子):

double source = 1123.0;

// 1124.0
double result = Math.Round(source / 2, MidpointRounding.AwayFromZero) * 2;
Run Code Online (Sandbox Code Playgroud)

演示:

double[] tests = new double[] {
     1.0,
  1123.1,
  1123.0,
  1122.9,
  1122.1,
  1122.0,
  1121.5,
  1121.0,
};

string report = string.Join(Environment.NewLine, tests
  .Select(item => $"{item,6:F1} -> {Math.Round(item / 2, MidpointRounding.AwayFromZero) * 2}"));

Console.Write(report);
Run Code Online (Sandbox Code Playgroud)

结果:

   1.0 -> 2     // In case of tie, next even value
1123.1 -> 1124
1123.0 -> 1124  // In case of tie, next even value
1122.9 -> 1122
1122.1 -> 1122
1122.0 -> 1122
1121.5 -> 1122
1121.0 -> 1122  // In case of tie, next even value
Run Code Online (Sandbox Code Playgroud)

  • 所有C#编译器是否将`source / 2`优化为`source * 0.5`?0.5可以精确表示为二进制double,因此非常安全。(FP mul是现代x86硬件上FP分割的大约1/3延迟和10倍的吞吐量:[浮点分割与浮点乘法](/sf/answers/3212944171/)) (2认同)

Dmi*_*lev 7

一个班轮:

double RoundToNearestEven(double value) =>
    Math.Truncate(value) + Math.Truncate(value) % 2;
Run Code Online (Sandbox Code Playgroud)

小提琴

说明:如果我们在浮点后有一个带有一些数字的偶数,我们需要摆脱那些数字.如果我们有一个奇数,我们需要做同样的事情,然后移动到保证是偶数的下一个整数.

PS感谢@DmitryBychenko指出,铸造double to long并不是最明智的想法.

  • @DmitryBychenko请注意,只要`double`的绝对值仍然很小,以及'double`实际上可以将偶数整数与其他数字区分开来,从'double`到`long`的转换不会失去幅度.从'2**53 == 9.007199254740994E + 15`及以上,_every_完全可表示的`double`已经是一个偶数整数.__当然,将'double``1E + 100`转换为`long`会丢失原始数字并导致不良结果仍然是完全正确的.__正确的实现,就像我们现在看到的那样,应该返回相同的`double`如果超过'2**53`. (2认同)