内置.Net 算法,可以将值舍入到最接近的10个间隔

如何,在 C # 四舍五入任何值到10的间隔?例如,如果我有11,我希望它返回10,如果我有136,那么我希望它返回140。

我可以很容易地用手做

return ((int)(number / 10)) * 10;

但我正在寻找一个内置的算法来做这项工作,像数学。圆()。我之所以不想手工完成,是因为我不想在我的项目中编写相同或相似的代码,即使是像上面这样简单的代码。

85381 次浏览

将浮点数舍入为整数类似于(int)(x + 0.5) ,而不是简单地将 x 转换为整数-如果您想要一个10的倍数,可以很容易地调整它。

如果你只想做整数运算,并将其四舍五入到十,那么试试(x + 10/2)/10 * 10。

编辑: 我注意到这个回复不符合原作者的要求,也是一种我不喜欢的有偏见的舍入形式。然而,另一个被接受的响应已经声明 Math.round ()是一个更好的解决方案。

使用数学。天花板总是四舍五入。

int number = 236;
number = (int)(Math.Ceiling(number / 10.0d) * 10);

模(%)得到余数,所以你得到:

// number = 236 + 10 - 6

将其放入扩展方法中

public static int roundupbyten(this int i){
// return i + (10 - i % 10); <-- logic error. Oops!
return (int)(Math.Ceiling(i / 10.0d)*10); // fixed
}


// call like so:
int number = 236.roundupbyten();

我应该按照我的第一直觉去使用数学。天花板

在计算 UPC 校验数字的时候,我在博客上写到了这一点

类库中没有内置的函数可以做到这一点。最接近的是 系统,数学,圆(),它仅用于将 Decimal 和 Double 类型的数字四舍五入到最接近的整数值。但是,如果使用的是。NET 3.5,这将允许你更干净利落地使用这个函数。

public static class ExtensionMethods
{
public static int RoundOff (this int i)
{
return ((int)Math.Round(i / 10.0)) * 10;
}
}


int roundedNumber = 236.RoundOff(); // returns 240
int roundedNumber2 = 11.RoundOff(); // returns 10

如果编程时使用的是。NET 框架中,只需从 RoundOff 函数中删除“ this”,然后像这样调用函数:

int roundedNumber = ExtensionMethods.RoundOff(236); // returns 240
int roundedNumber2 = ExtensionMethods.RoundOff(11); // returns 10

这可能有点太晚了,但我想这也许有一天能帮上忙..。

我试过这个:

public int RoundOff(int number, int interval){
int remainder = number % interval;
number += (remainder < interval / 2) ? -remainder : (interval - remainder);
return number;
}

使用方法:

int number = 11;
int roundednumber = RoundOff(number, 10);

这样,您就可以选择间隔的一半是四舍五入还是四舍五入。=)

我不喜欢使用 Math库,也不喜欢使用浮点运算,所以我的建议是像下面这样做整数运算,我会四舍五入到下一个1K。如果不想重复,可以用方法或者 lambda 代码片段或者其他东西来包装它。

int MyRoundedUp1024Int = ((lSomeInteger + 1023) / 1024) * 1024;

我还没有运行性能测试与其他方式相比,但我敢打赌,这是最快的方式做到这一点,保存可能移动和旋转位版本的这一点。

老问题,但这里有一个方法,做什么已经问加上我扩展它能够四舍五入任何数字的西格无花果的数量你想要的。

    private double Rounding(double d, int digits)
{
int neg = 1;
if (d < 0)
{
d = d * (-1);
neg = -1;
}


int n = 0;
if (d > 1)
{
while (d > 1)
{
d = d / 10;
n++;
}
d = Math.Round(d * Math.Pow(10, digits));
d = d * Math.Pow(10, n - digits);
}
else
{
while (d < 0.1)
{
d = d * 10;
n++;
}
d = Math.Round(d * Math.Pow(10, digits));
d = d / Math.Pow(10, n + digits);
}


return d*neg;
}




private void testing()
{
double a = Rounding(1230435.34553,3);
double b = Rounding(0.004567023523,4);
double c = Rounding(-89032.5325,2);
double d = Rounding(-0.123409,4);
double e = Rounding(0.503522,1);
Console.Write(a.ToString() + "\n" + b.ToString() + "\n" +
c.ToString() + "\n" + d.ToString() + "\n" + e.ToString() + "\n");
}

下面是我如何四舍五入到任意因子的最接近倍数,而不需要从整型转换为浮点值。这适用于从 int.MinValue + 1int.MaxValue的任何 int 类型

我使用 离零方程的一半是圆的Round(x) = sgn(x)*Floor(Abs(x) + 0.5),事实上,Floor(z) = z - (z%1),和我想要的输出方程 F(value, factor) = Round(value/factor)*factor导出一个方程,不需要精确的十进制除法。

public static int RoundToNearestMultipleOfFactor(this int value, int 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);
}

下面是整个扩展方法类,其中包含 intlong的方法,以及只向零舍入或从零舍入的方法。

/// <summary>
/// Extension methods for rounding integral numeric types
/// </summary>
public static class IntegralRoundingExtensions
{
/// <summary>
/// Rounds to the nearest multiple of a <paramref name="factor"/> using <see cref="MidpointRounding.AwayFromZero"/> for midpoints.
/// <para>
/// Performs the operation Round(value / factor) * factor without converting to a floating type.
/// </para>
/// </summary>
/// <param name="value">The value to round.</param>
/// <param name="factor">The factor to round to a multiple of. Must not be zero. Sign does not matter.</param>
/// <remarks>
/// Uses math derived from the <see href="https://en.wikipedia.org/wiki/Rounding#Round_half_away_from_zero">Round half away from zero equation</see>: y = sgn(x)*Floor(Abs(x) + 0.5) and floor equation: Floor(z) = z - (z % 1)
/// </remarks>
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="factor"/> is zero</exception>
/// <seealso cref="MidpointRounding"/>
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) + halfAbsFactor) % factor));
//fix overflow
return value + Math.Sign(value) * (halfAbsFactor - (Math.Abs(value) % factor + halfAbsFactor % factor) % factor);
}


/// <summary>
/// Round to the nearest multiple of <paramref name="factor"/> with magnitude less than or equal to <paramref name="value"/>.
/// </summary>
/// <param name="value">The value to round.</param>
/// <param name="factor">The factor to round to a multiple of. Must not be zero. Sign does not matter.</param>
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="factor"/> is zero</exception>
public static long RoundToMultipleOfFactorTowardZero(this long value, long factor)
{
if (factor == 0)
{
throw new ArgumentOutOfRangeException(nameof(factor), factor, "Cannot be zero");
}


var remainder = value % factor; // negative iff value is negative


if (remainder == 0)
{
return value;
}


return value - remainder;
}


/// <summary>
/// Round to the nearest multiple of <paramref name="factor"/> with magnitude greater than or equal to <paramref name="value"/>.
/// </summary>
/// <param name="value">The value to round.</param>
/// <param name="factor">The factor to round to a multiple of. Must not be zero. Sign does not matter.</param>
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="factor"/> is zero</exception>
public static long RoundToMultipleOfFactorAwayFromZero(this long value, long factor)
{
if (factor == 0)
{
throw new ArgumentOutOfRangeException(nameof(factor), factor, "Cannot be zero");
}


var remainder = value % factor; // negative iff value is negative


if (remainder == 0)
{
return value;
}


return value - remainder + Math.Sign(value) * Math.Abs(factor);
}


/// <summary>
/// Rounds to the nearest multiple of a <paramref name="factor"/> using <see cref="MidpointRounding.AwayFromZero"/> for midpoints.
/// <para>
/// Performs the operation Round(value / factor) * factor without converting to a floating type.
/// </para>
/// </summary>
/// <param name="value">The value to round.</param>
/// <param name="factor">The factor to round to a multiple of. Must not be zero. Sign does not matter.</param>
/// <remarks>
/// Uses math derived from the <see href="https://en.wikipedia.org/wiki/Rounding#Round_half_away_from_zero">Round half away from zero equation</see>: y = sgn(x)*Floor(Abs(x) + 0.5) and floor equation: Floor(z) = z - (z % 1)
/// </remarks>
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="factor"/> is zero</exception>
/// <seealso cref="MidpointRounding"/>
public static int RoundToNearestMultipleOfFactor(this int value, int 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) + halfAbsFactor) % factor));
//fix overflow
return value + Math.Sign(value) * (halfAbsFactor - (Math.Abs(value) % factor + halfAbsFactor % factor) % factor);
}


/// <summary>
/// Round to the nearest multiple of <paramref name="factor"/> with magnitude less than or equal to <paramref name="value"/>.
/// </summary>
/// <param name="value">The value to round.</param>
/// <param name="factor">The factor to round to a multiple of. Must not be zero. Sign does not matter.</param>
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="factor"/> is zero</exception>
public static int RoundToMultipleOfFactorTowardZero(this int value, int factor)
{
if (factor == 0)
{
throw new ArgumentOutOfRangeException(nameof(factor), factor, "Cannot be zero");
}


var remainder = value % factor; // negative iff value is negative


if (remainder == 0)
{
return value;
}


return value - remainder;
}


/// <summary>
/// Round to the nearest multiple of <paramref name="factor"/> with magnitude greater than or equal to <paramref name="value"/>.
/// </summary>
/// <param name="value">The value to round.</param>
/// <param name="factor">The factor to round to a multiple of. Must not be zero. Sign does not matter.</param>
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="factor"/> is zero</exception>
public static int RoundToMultipleOfFactorAwayFromZero(this int value, int factor)
{
if (factor == 0)
{
throw new ArgumentOutOfRangeException(nameof(factor), factor, "Cannot be zero");
}


var remainder = value % factor; // negative iff value is negative


if (remainder == 0)
{
return value;
}


return value - remainder + Math.Sign(value) * Math.Abs(factor);
}
}

据我所知,没有一个本地内置的 c # 库可以将整数舍入到最接近的十位数。

如果您正在使用 c # 8或更高版本,您可以创建小开关表达式实用程序方法,这些方法可以做很多很酷的有用的事情。如果您使用的是旧版本,可以使用 if/elseswitch case块:

public static int RoundIntToTens(int anInt)
=> (anInt, (anInt < 0 ? 0 - anInt : anInt) % 10) switch
{
// If int needs to be "round down" and is negative or positive
(>= 0, < 5) or (< 0, < 5) => anInt - anInt % 10,
// If int needs to be "round up" and is NOT negative (but might be 0)
(>= 0, >= 5) => anInt + (10 - anInt % 10),
// If int needs to be "round up" and is negative
(< 0, >= 5) => anInt - (10 + anInt % 10)
};

您必须在任何使用它的地方导入它,但是对于任何库来说都是如此,除非有一种方法可以将类添加到全局名称空间中。