四舍五入到一个数字的倍数
本文关键字:数字 一个 四舍五入 | 更新日期: 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,则模式可以是AwayFromZero
或ToEven
。如果您使用的是较新版本的.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!!!");
}