四舍五入到一个数字的倍数

本文关键字:数字 一个 四舍五入 | 更新日期: 2023-09-27 18:28:15

我正试图创建一个函数,将一个数字四舍五入到给定数字的最接近倍数作为整数。

所以如果数字是15,我们就有

  • 14.4轮至15轮
  • -14.4轮至-15轮
  • 14.5轮至15轮
  • 28轮至30轮
  • -28轮至-30轮

等等。我已经准备好了一些代码,但似乎没有像预期的那样工作:

public static int RoundToFactor(float number, float Factor)
{
        int returnNumber;
        if((number%Factor) == 0) {
            returnNumber = (int)number;
        }
        returnNumber = (int) (Mathf.Round(number/Factor)*Factor);
        return returnNumber;
}

四舍五入到一个数字的倍数

这里有一个使用简单逻辑和System.Math方法(可能会更优化)的扩展方法。

using System;
public static class NumericRoundingExtensions
{
    /// <summary>
    /// Rounds a number to the nearest multiple of another number
    /// </summary>
    /// <param name="value">The value to round</param>
    /// <param name="factor">The factor to round to a multiple of. Must not be zero.</param>
    /// <param name="mode">Defines direction to round if <paramref name="value"/> is exactly halfway between two multiples of <paramref name="factor"/></param>
    /// <remarks>
    /// Use with caution when <paramref name="value"/> is large or <paramref name="factor"/> is small.
    /// </remarks>
    /// <exception cref="DivideByZeroException">If <paramref name="factor"/> is zero</exception>
    public static double RoundToNearestMultipleOfFactor(this double value, double factor, MidpointRounding mode = MidpointRounding.AwayFromZero)
    {
        return Math.Round(value / factor, mode) * factor;
    }
}

如果您使用的是.Net Framework,则模式可以是AwayFromZeroToEven。如果您使用的是较新版本的.Net,则有六种不同的模式可用于处理介于因子的两倍之间的值。中点舍入文档

我在搜索一种不转换为浮点的long值的方法时发现了这个问题。如果您碰巧使用整型,如long或int,那么最好使用以下类型:

public static long RoundToNearestMultipleOfFactor(this long value, long factor)
{
    if (factor == 0)
    {
        throw new ArgumentOutOfRangeException(nameof(factor), factor, "Cannot be zero");
    }
    var halfAbsFactor = Math.Abs(factor) >> 1;
    return value + Math.Sign(value) * (halfAbsFactor - (Math.Abs(value) % factor + halfAbsFactor % factor) % factor);
}

有关积分类型的完整扩展方法类,请参阅我对类似问题

的回答

这是我制作的一个方法。它应该适合你的需要。我添加了一个额外的参数,要求在它同样接近时向上或向下取整。(如果你注意到数字为负数时看起来是错误的,例如199四舍五入到最接近的2因子,必要时向上取整为200。将199更改为-199,结果变为-198,这不是一个错误,它只是四舍五入。)

public static double RoundToFactor(double Number, int Factor, bool RoundDirection = true)
    {/*round direction: in the event that the distance is 
      * equal from both next factors round up (true) down (false)*/
        double multiplyBy;
        if ((Number % Factor).Equals(0f))
        {
            return Number;
        }
        else
        {
            multiplyBy = Math.Round(Number / Factor);
            int Low = (int)multiplyBy - 1;
            int Mid = (int)multiplyBy;
            int High = (int)multiplyBy + 1;
            List<double> li = new List<double>() { Low, Mid, High };
            double minDelta = double.MaxValue;
            double Closest = 0d;
            foreach (double dbl in li)
            {
                double db = dbl * Factor;
                double Delta = (db < Number) ? (Number - db) : (db - Number);
                if (RoundDirection ? Delta <= minDelta : Delta < minDelta)
                {
                    minDelta = Delta;
                    Closest = db;
                }
            }
            return Closest;
        }
        throw new Exception("Math has broken!!!");
    }