如何将小数舍入到C#中的特定分数?

时间:2009-02-02 02:13:46

标签: c# .net algorithm math

在C#中舍入一个数字很容易:

Math.Round(1.23456, 4); // returns 1.2346

但是,我想要舍入一个数字,使得数字的小数部分舍入到预定义分数的最接近的小数部分(例如1/8),并且我试图找出.NET库是否已经有这是内置的。

所以,例如,如果我想将十进制数舍入到整数八,那么我想调用类似的东西:

Math.RoundFractional(1.9, 8); // and have this yield 1.875
Math.RoundFractional(1.95, 8); // and have this yield 2.0

所以第一个参数是我要舍入的数字,第二个参数指示舍入分数。所以在这个例子中,在进行舍入后,小数点后面的数字只能是八个值中的一个:.000,.125,.250,.375,。500,.625,.750,.875

问题:这个功能是否在某个地方内置于.NET中?如果没有,是否有人有资源链接解释如何解决这个问题?

3 个答案:

答案 0 :(得分:17)

你可以这样做:

Math.Round(n * 8) / 8.0

答案 1 :(得分:6)

不知道它是否内置于.NET中,但我只是这样做:

Math.Round(x * 8, 0) / 8;

将它四舍五入到最接近的第8位。

将您喜欢的号码替换为其他“分辨率”。

答案 2 :(得分:0)

这是一个较晚的答复,但对于任何正在寻找更全面的解决方案来转换原始文章所述的Double的人来说,这都是对的。下面是一个静态类,为双打提供了扩展方法,可以通过多种方式来实现此目的。

using System;

/// <summary>
/// Author: Aniceto Moreno Jr
/// Email:  amorenojr@outlook.com
/// Date:   03/23/2020
/// </summary>
public static class DoubleExtensions
{
    /// <summary>
    /// Rounds the value to the nearest increment. 
    /// Assumes mid-point rounding, value >= 0.5 rounds up, value < 0.5 rounds down.
    /// </summary>
    /// <param name="Value"></param>
    /// <param name="increment">Enter the increment value to round toward.</param>
    /// <returns>Returns the value rounded to the nearest increment value.</returns>
    public static double RoundToNearest(this double Value, double increment)
    {
        // Returning the value rounded to the nearest increment value.
        return Math.Round(Value * Math.Pow(increment, -1), 0) * increment;
    }

    /// <summary>
    /// Rounds down the value to the nearest increment. 
    /// </summary>
    /// <param name="Value"></param>
    /// <param name="increment">Enter the increment value to round down toward.</param>
    /// <returns>Returns the value rounded down to the nearest increment value.</returns>
    public static double FloorToNearest(this double Value, double increment)
    {
        // Returning the value rounded down to the nearest increment value.
        return Math.Floor(Value * Math.Pow(increment, -1)) * increment;
    }

    /// <summary>
    /// Rounds up the value to the nearest increment. 
    /// </summary>
    /// <param name="Value"></param>
    /// <param name="increment">Enter the increment value to round up toward.</param>
    /// <returns>Returns the value rounded up to the nearest increment value.</returns>
    public static double CeilingToNearest(this double Value, double increment)
    {
        // Returning the value rounded up to the nearest increment value.
        return Math.Ceiling(Value * Math.Pow(increment, -1)) * increment;
    }

    /// <summary>
    /// Rounds the value down to the nearest imperial fractional increment
    /// and converts the value into an Inch-Fraction (IF) string. 
    /// Note: Assumes value is in inches and does not convert to Feet-Inch-Fraction (FIF)
    /// </summary>
    /// <param name="Value"></param>
    /// <param name="maxDenominator">Enter the maximum denominator to round toward (i.e. 1/16 --> 16)</param>
    /// <returns>Returns the value rounded down to the nearest increment value based on the maxDenominator.</returns>
    public static string FloorToInchFraction(this double Value, int maxDenominator)
    {
        // Returning the rounded value converted into an Inch-Fraction (IF) string.
        return Value.FloorToNearest(Math.Pow(maxDenominator, -1)).ToInchFraction(maxDenominator);
    }

    /// <summary>
    /// Rounds the value up to the nearest imperial fractional increment
    /// and converts the value into an Inch-Fraction (IF) string. 
    /// Note: Assumes value is in inches and does not convert to Feet-Inch-Fraction (FIF)
    /// </summary>
    /// <param name="Value"></param>
    /// <param name="maxDenominator">Enter the maximum denominator to round toward (i.e. 1/16 --> 16)</param>
    /// <returns>Returns the value rounded up to the nearest increment value based on the maxDenominator.</returns>
    public static string CeilingToInchFraction(this double Value, int maxDenominator)
    {
        // Returning the rounded value converted into a fraction string.
        return Value.CeilingToNearest(Math.Pow(maxDenominator, -1)).ToInchFraction(maxDenominator);
    }

    /// <summary>
    /// Rounds the value to the nearest increment value based on the maximum denominator specified.
    /// Assumes mid-point rounding, value >= 0.5 rounds up, value < 0.5 rounds down.
    /// </summary>
    /// <param name="Value"></param>
    /// <param name="maxDenominator">Enter the maximum denominator to round toward (i.e. 1/16 --> 16)</param>
    /// <returns>Returns the value rounded to the nearest increment value based on the maxDenominator.</returns>
    public static string ToInchFraction(this double Value, int maxDenominator)
    {
        // Calculating the nearest increment of the value
        // argument based on the denominator argument.
        double incValue = Value.RoundToNearest(Math.Pow(maxDenominator, -1));

        // Identifying the whole number of the argument value.
        int wholeValue = (int)Math.Truncate(incValue);

        // Calculating the remainder of the argument value and the whole value.
        double remainder = incValue - wholeValue;

        // Checking for the whole number case and returning if found.
        if (remainder == 0.0) { return wholeValue.ToString() + (char)34; }

        // Iterating through the exponents of base 2 values until the
        // maximum denominator value has been reached or until the modulus
        // of the divisor.
        for (int i = 1; i < (int)Math.Log(maxDenominator, 2) + 1; i++)
        {
            // Calculating the denominator of the current iteration
            double denominator = Math.Pow(2, i);

            // Calculating the divisor increment value
            double divisor = Math.Pow(denominator, -1);

            // Checking if the current denominator evenly divides the remainder
            if ((remainder % divisor) == 0.0) // If, yes
            {
                // Calculating the numerator of the remainder 
                // given the calculated denominator
                int numerator = Convert.ToInt32(remainder * denominator);

                // Returning the resulting string from the conversion.
                return (wholeValue > 0 ? wholeValue.ToString() + "-" : "") + numerator.ToString() + "/" + ((int)denominator).ToString() + (char)34;
            }
        }

        // Returns Error if something goes wrong.
        return "Error";
    }

    /// <summary>
    /// Rounds the value down to the nearest imperial fractional increment
    /// and converts the value into an Feet-Inch-Fraction (FIF) string. 
    /// </summary>
    /// <param name="Value"></param>
    /// <param name="maxDenominator">Enter the maximum denominator to round toward (i.e. 1/16 --> 16)</param>
    /// <returns>Returns the value rounded down to the nearest increment value based on the maxDenominator.</returns>
    public static string FloorToFeetInchFraction(this double Value, int maxDenominator)
    {
        // Returning the rounded value converted into an Feet-Inch-Fraction (FIF) string.
        return Value.FloorToNearest(Math.Pow(maxDenominator, -1)).ToFeetInchFraction(maxDenominator);
    }

    /// <summary>
    /// Rounds the value up to the nearest imperial fractional increment
    /// and converts the value into an Feet-Inch-Fraction (FIF) string. 
    /// </summary>
    /// <param name="Value"></param>
    /// <param name="maxDenominator">Enter the maximum denominator to round toward (i.e. 1/16 --> 16)</param>
    /// <returns>Returns the value rounded up to the nearest increment value based on the maxDenominator.</returns>
    public static string CeilingToFeetInchFraction(this double Value, int maxDenominator)
    {
        // Returning the rounded value converted into a fraction string.
        return Value.CeilingToNearest(Math.Pow(maxDenominator, -1)).ToFeetInchFraction(maxDenominator);
    }

    /// <summary>
    /// Rounds the value to the nearest increment value based on the maximum denominator specified.
    /// Assumes mid-point rounding, value >= 0.5 rounds up, value < 0.5 rounds down.
    /// </summary>
    /// <param name="Value"></param>
    /// <param name="maxDenominator">Enter the maximum denominator to round toward (i.e. 1/16 --> 16)</param>
    /// <returns>Returns the value rounded to the nearest increment value based on the maxDenominator.</returns>
    public static string ToFeetInchFraction(this double Value, int maxDenominator)
    {
        // Calculating the nearest increment of the value
        // argument based on the denominator argument.
        double incValue = Value.RoundToNearest(Math.Pow(maxDenominator, -1));

        // Calculating the remainder of the argument value and the whole value.
        double FeetInch = Math.Truncate(incValue) / 12.0;

        // Calculating the remainder of the argument value and the whole value.
        int Feet = (int)Math.Truncate(FeetInch);

        // Calculating remaining inches.
        incValue -= (double)(Feet * 12.0);

        // Returns the feet plus the remaining amount converted to inch fraction.
        return (Feet > 0 ? Feet.ToString() + (char)39 + " " : "") + incValue.ToInchFraction(maxDenominator);
    }
}

使用和实施示例:

double testValue0 = 1.0625; // 1―1/16"
Console.WriteLine(testValue0.ToInchFraction(32)); // 1―1/16"

double testValue1 = 1.515625; // 1―33/64"
Console.WriteLine(testValue1.CeilingToInchFraction(16)); // 1―9/16"

double testValue2 = 1.03125; // 1―1/32"
Console.WriteLine(testValue2.FloorToInchFraction(16)); // 1"

double testValue3 = 5 / 25.4; // 5 mm = 0.1969 in
Console.WriteLine(testValue3.ToInchFraction(32)); // 3/16"
Console.WriteLine(testValue3.ToInchFraction(64)); // 13/64"