Встроенный алгоритм .Net для округления значения до ближайшего интервала 10

Как в С# округлить любое значение до 10 интервалов? Например, если у меня 11, я хочу, чтобы он вернул 10, если у меня 136, то я хочу, чтобы он вернул 140.

Я легко могу сделать это вручную

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

Но я ищу встроенный алгоритм для выполнения этой работы, что-то вроде Math.Round(). Причина, по которой я не хочу делать это вручную, заключается в том, что я не хочу писать один и тот же или похожий фрагмент кода во всех своих проектах, даже для чего-то такого простого, как выше.


person Graviton    schedule 08.11.2008    source источник
comment
Если это работает, зачем вам что-то еще? Просто оберните его в метод расширения или общую библиотеку и запустите с ним.   -  person John Sheehan    schedule 08.11.2008
comment
((число + 5)/10) * 10 -- хороший повод найти встроенный. :-)   -  person Adam Liss    schedule 08.11.2008
comment
Я заметил, что с этим вопросом возникла путаница, и вам, вероятно, следует отредактировать заголовок или сообщение, чтобы сделать его более понятным. В частности, вы хотите всегда округлять или округлять до ближайших 10?   -  person Raymond Martineau    schedule 08.11.2008
comment
Рэймонд, основываясь на фактическом содержании вопроса, а не на заголовке, очевидно, что речь идет об округлении до ближайших 10. Но я также заметил эту двусмысленность и согласен, что заголовок должен быть изменен, чтобы соответствовать.   -  person Chris Charabaruk    schedule 08.11.2008
comment
@Adam: Что плохого в том, чтобы обернуть простую и понятную строку кода в метод? Мне не кажется сложным или запутанным.   -  person Ed S.    schedule 24.11.2009


Ответы (6)


В библиотеке классов нет встроенной функции, которая это сделает. Наиболее близким является System.Math.Round(), который предназначена только для округления чисел типов 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 framework, просто удалите this из функции RoundOff и вызовите функцию следующим образом:

int roundedNumber = ExtensionMethods.RoundOff(236); // returns 240
int roundedNumber2 = ExtensionMethods.RoundOff(11); // returns 10
person Chris Charabaruk    schedule 08.11.2008
comment
С этим кодом куча проблем, а именно он не компилируется (отсутствует возвращаемый тип) и не округляется до ближайшего. В вашем примере он возвращает 230 и 10. - person Dave Van den Eynde; 03.03.2009
comment
Он все равно не вернет 240, потому что вы округляете в меньшую сторону. - person Dave Van den Eynde; 03.03.2009
comment
На самом деле запустить его. Вот исходник (включая тестовый класс) и даже сборка исходника. Работает, и правильно. labs.coldacid.net/code/number-rounding-extension-method - person Chris Charabaruk; 03.03.2009
comment
Ах, но ваш оригинальный ответ вообще не использовал Math.Round(). - person Dave Van den Eynde; 03.03.2009
comment
Кроме того, вы изменили 10 на 10.0, что полезно знать, иначе не скомпилируется. - person Dave Van den Eynde; 03.03.2009
comment
Вопрос требует округления, но этот ответ округляется. Если вы введете 11, вы должны получить 20, а не 10. Вот почему вам нужно Math.Ceiling(). - person Dan Diplo; 14.03.2012
comment
Дэн Дипло: Уже в следующем предложении, где ОП объясняет, чего он хочет, описывается округление. Прочитайте весь вопрос, а не только его первое предложение. - person Chris Charabaruk; 14.03.2012

Используйте Math.Ceiling, чтобы всегда округлять значения в большую сторону.

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();

выше отредактировано: я должен был пойти с моим первым инстинктом использовать Math.Ceiling

Я записал об этом в блоге при расчете контрольных цифр UPC.

person Armstrongest    schedule 08.11.2008
comment
Попробуйте с 240. Что получится? Или, если уж на то пошло, 11. - person Chris Charabaruk; 08.11.2008

Это может быть слишком поздно, но я думаю, что когда-нибудь это может быть хорошим подспорьем...

Я пробовал это:

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);

Таким образом, у вас есть возможность округлить половину интервала в большую или меньшую сторону. знак равно

person Jronny    schedule 24.11.2009

Округление числа с плавающей запятой до целого числа похоже на (int)(x+0.5), в отличие от простого приведения x — если вам нужно число, кратное 10, вы можете легко это адаптировать.

Если вы просто хотите вычислить целые числа и округлить их до десяти, попробуйте (x+10/2)/10*10.

Редактировать: я заметил, что этот ответ не соответствует запросу автора оригинала, а также представляет собой предвзятую форму округления, которую я предпочитаю не делать. Однако в другом принятом ответе уже говорилось о Math.round(), гораздо лучшем решении.

person Raymond Martineau    schedule 08.11.2008
comment
Я должен сказать, что, несмотря на то, что я часто использовал этот трюк в прошлом, Math.Round выглядит намного чище. - person Dave Van den Eynde; 03.03.2009

Старый вопрос, но вот способ сделать то, что было задано, плюс я расширил его, чтобы иметь возможность округлять любое число до нужного вам количества цифр.

    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");
   }
person Lucas925    schedule 24.01.2013

Я предпочитаю не вводить библиотеку Math и не переходить к числам с плавающей запятой, поэтому я предлагаю просто выполнить целочисленную арифметику, как показано ниже, где я округляю до следующего 1K. Оберните его в метод или лямбда-фрагмент или что-то еще, если вы не хотите повторяться.

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

Я не проводил тесты производительности по сравнению с другими способами, но держу пари, что это самый быстрый способ сделать это, за исключением, возможно, версии со сдвигом и вращением битов.

person Dave    schedule 06.08.2012