Як округнути до найближчого 0,5?


102

Я повинен відображати рейтинги, і для цього мені потрібні наступні кроки:

Якщо число 1,0, воно повинно дорівнювати 1
Якщо число 1,1 повинно дорівнювати 1
Якщо число 1,2 повинно дорівнювати 1
Якщо число 1,3 повинно бути рівним 1,5
Якщо число 1,4 має бути рівним 1.5
Якщо число 1,5 має бути рівне 1,5
Якщо число 1,6 має бути рівне 1,5
Якщо число 1,7 має бути рівне 1,5
Якщо число 1,8 має бути рівне 2,0
Якщо число 1,9 повинно бути рівним 2.0
Якщо число 2,0 повинно дорівнювати 2,0
Якщо число 2,1 повинно бути рівним 2,0
і так далі ...

Чи існує простий спосіб обчислити необхідні значення?


"і так далі ..." чи включає в себе кінцеві числа, близькі до максимального представного значення?
chux

Відповіді:


206

Помножте рейтинг на 2, потім обведіть його Math.Round(rating, MidpointRounding.AwayFromZero), а потім діліть це значення на 2.

Math.Round(value * 2, MidpointRounding.AwayFromZero) / 2


4
Мені не потрібно набирати манекенів, мені потрібно набрати для розумних робіт
Ніл N

3
Не ідеальний! як щодо цілого переповнення! Ви можете обчислити лише половину можливих цілих чисел.
Елазар Лейбович

2
@Elazar - якщо ти можеш оцінити до 1,073,741,823-го, я не можу придумати єдиний випадок використання, коли б ти не переймався, якщо це "мільярд півтора" або "один мільярд один" - якщо це справді проблема то в схемі рейтингу є щось непорозуміле :)
Джон Раш,

4
Спочатку поділіть, а потім помножте. Це усуне проблему переповнення, а також дозволить округлити довільне число.
Benjol

8
@Benjol, розділення спочатку, а потім округлення призведе до округлення до найближчого коефіцієнта 2, а не до коефіцієнта половини. Неправильно.
Нахт

67

Помножте на 2, округлити, потім розділіть на 2

якщо ви хочете найближчу чверть, помножте на 4, розділіть на 4 тощо


16

Ось пара методів, про які я писав, які завжди будуть округляти чи зменшувати будь-яке значення.

public static Double RoundUpToNearest(Double passednumber, Double roundto)
{
    // 105.5 up to nearest 1 = 106
    // 105.5 up to nearest 10 = 110
    // 105.5 up to nearest 7 = 112
    // 105.5 up to nearest 100 = 200
    // 105.5 up to nearest 0.2 = 105.6
    // 105.5 up to nearest 0.3 = 105.6

    //if no rounto then just pass original number back
    if (roundto == 0)
    {
        return passednumber;
    }
    else
    {
        return Math.Ceiling(passednumber / roundto) * roundto;
    }
}

public static Double RoundDownToNearest(Double passednumber, Double roundto)
{
    // 105.5 down to nearest 1 = 105
    // 105.5 down to nearest 10 = 100
    // 105.5 down to nearest 7 = 105
    // 105.5 down to nearest 100 = 100
    // 105.5 down to nearest 0.2 = 105.4
    // 105.5 down to nearest 0.3 = 105.3

    //if no rounto then just pass original number back
    if (roundto == 0)
    {
        return passednumber;
    }
    else
    {
        return Math.Floor(passednumber / roundto) * roundto;
    }
}

2

Є кілька варіантів. Якщо продуктивність викликає занепокоєння, протестуйте їх, щоб побачити, що працює найшвидше у великому циклі.

double Adjust(double input)
{
    double whole = Math.Truncate(input);
    double remainder = input - whole;
    if (remainder < 0.3)
    {
        remainder = 0;
    }
    else if (remainder < 0.8)
    {
        remainder = 0.5;
    }
    else
    {
        remainder = 1;
    }
    return whole + remainder;
}

Це має працювати, але це не так елегантно, як деякі рішення. Помноження та використання системної бібліотеки просто сексуально.
captncraig

Продуктивність, як правило, важливіша, і це може призвести до меншого часу, ніж рішення множення та ділення.
Джон Фішер

3
Цей код невірний. Оскільки в арифметиці з подвоєннями зазвичай є невеликі помилки округлення, така операція, як 4.8 - 4.0, може дати, наприклад, 0.799999 .... У цьому випадку наведений вище код закруглює 4,5. Також краще використовувати Math.Floor замість Math.Truncate, оскільки зараз негативні числа не закруглені. Я віддаю перевагу прийнятій відповіді, тому що вона простіша і менш схильна до помилок впровадження.
Accipitridae

1
decimal d = // your number..

decimal t = d - Math.Floor(d);
if(t >= 0.3d && t <= 0.7d)
{
    return Math.Floor(d) + 0.5d;
}
else if(t>0.7d)
    return Math.Ceil(d);
return Math.Floor(d);

1

Звучить так, що потрібно округлити до найближчого 0,5. Я не бачу жодної версії roundAPI C #, яка б це робила (одна версія вимагає округлення кількох десяткових цифр, що не те саме).

Якщо припустити, що ви маєте справу лише з цілими числами десятих, достатньо обчислити round (num * 2) / 2. Якщо ви використовуєте довільно точні десятки, воно стає складніше. Будемо сподіватися, що ви цього не зробите.


0

У мене теж були проблеми з цією проблемою. Я кодую в основному в Actioncript 3.0, що є базовим кодуванням для платформи Adobe Flash, але в Мовах є модулі:

Я придумав таке рішення:

//Code for Rounding to the nearest 0.05
var r:Number = Math.random() * 10;  // NUMBER - Input Your Number here
var n:int = r * 10;   // INTEGER - Shift Decimal 2 places to right
var f:int = Math.round(r * 10 - n) * 5;// INTEGER - Test 1 or 0 then convert to 5
var d:Number = (n + (f / 10)) / 10; //  NUMBER - Re-assemble the number

trace("ORG No: " + r);
trace("NEW No: " + d);

Це досить це. Зверніть увагу на використання "Чисел" та "Цілих чисел" та спосіб їх обробки.

Щасти!


0
Public Function Round(ByVal text As TextBox) As Integer
    Dim r As String = Nothing
    If text.TextLength > 3 Then
        Dim Last3 As String = (text.Text.Substring(text.Text.Length - 3))
        If Last3.Substring(0, 1) = "." Then
            Dim dimcalvalue As String = Last3.Substring(Last3.Length - 2)
            If Val(dimcalvalue) >= 50 Then
                text.Text = Val(text.Text) - Val(Last3)
                text.Text = Val(text.Text) + 1
            ElseIf Val(dimcalvalue) < 50 Then
                text.Text = Val(text.Text) - Val(Last3)
            End If
        End If
    End If
    Return r
End Function

4
Цей код не схожий на C #, як потрібно у запитанні. Що це робить? Будь ласка, надайте трохи пояснень, а не просто кусковий код не визначеною мовою.
AdrianHHH

-1

Правильний спосіб зробити це:

  public static Decimal GetPrice(Decimal price)
            {
                var DecPrice = price / 50;
                var roundedPrice = Math.Round(DecPrice, MidpointRounding.AwayFromZero);
                var finalPrice = roundedPrice * 50;

                return finalPrice;

            }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.