Làm cách nào để làm tròn đến 0,5 gần nhất?


102

Tôi phải hiển thị xếp hạng và tôi cần các mức tăng như sau:

Nếu số là 1,0 thì phải bằng 1
Nếu số là 1,1 thì bằng 1
Nếu số là 1,2 thì phải bằng 1
Nếu số là 1,3 thì bằng 1,5
Nếu số là 1,4 thì bằng 1,5
Nếu số là 1,5 phải bằng 1,5
Nếu số 1,6 phải bằng 1,5
Nếu số 1,7 phải bằng 1,5
Nếu số 1,8 phải bằng 2,0
Nếu số 1,9 phải bằng 2,0
Nếu số là 2,0 thì bằng 2,0
Nếu số là 2,1 thì bằng 2,0
và cứ tiếp tục như vậy ...

Có cách nào đơn giản để tính các giá trị cần thiết không?


"vân vân ..." có bao gồm các số hữu hạn gần với giá trị có thể biểu diễn lớn nhất không?
chux - Phục hồi Monica

Câu trả lời:


206

Nhân xếp hạng của bạn với 2, sau đó làm tròn bằng cách sử dụng Math.Round(rating, MidpointRounding.AwayFromZero), sau đó chia giá trị đó cho 2.

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


4
Tôi không cần gõ cho núm vú cao su, tôi cần gõ cho Smarties
Neil N

3
Không hoàn hảo! những gì về tràn số nguyên! Bạn chỉ có thể tính một nửa số nguyên có thể.
Elazar Leibovich

2
@Elazar - nếu bạn có thể được xếp hạng cao tới thứ 1,073,741,823, tôi không thể nghĩ ra một trường hợp sử dụng duy nhất mà bạn sẽ quan tâm nếu đó là "một tỷ rưỡi" hay "một tỷ một" - nếu đó thực sự là một vấn đề sau đó có cái gì đó vốn đã thiếu sót với các chương trình xếp hạng :)
John Rasch

4
Chia trước, nhân sau. Điều này sẽ loại bỏ vấn đề tràn, và cũng cho phép bạn làm tròn đến một số tùy ý.
Benjol

8
@Benjol, chia trước và sau đó làm tròn sẽ làm cho nó làm tròn đến hệ số gần nhất của 2, thay vì nhân tố của một nửa. Không chính xác.
Nacht

67

Nhân với 2, làm tròn, rồi chia cho 2

nếu bạn muốn một phần tư gần nhất, hãy nhân với 4, chia cho 4, v.v.


16

Dưới đây là một số phương pháp tôi đã viết sẽ luôn làm tròn lên hoặc xuống bất kỳ giá trị nào.

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

Có một số tùy chọn. Nếu hiệu suất là mối quan tâm, hãy kiểm tra chúng để xem cái nào hoạt động nhanh nhất trong một vòng lặp lớn.

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

Điều này sẽ hoạt động, nhưng nó không thanh lịch như một số giải pháp được đưa ra. Nhân và sử dụng thư viện hệ thống chỉ là gợi cảm.
captncraig

Hiệu suất thường quan trọng hơn và điều này có thể mất ít thời gian hơn các giải pháp nhân và chia.
John Fisher

3
Mã này không đúng. Vì số học với nhân đôi thường có một số lỗi làm tròn nhỏ, một phép toán như 4.8 - 4.0 có thể cho ví dụ 0.799999 .... Trong trường hợp này, mã trên sẽ làm tròn thành 4,5. Cũng tốt hơn nên sử dụng Math.Floor thay vì Math.Truncate, bởi vì ngay bây giờ các số âm không được làm tròn. Tôi thích câu trả lời được chấp nhận hơn, vì nó đơn giản hơn và ít bị lỗi triển khai hơn.
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

Có vẻ như bạn cần làm tròn chính xác đến 0,5. Tôi không thấy phiên bản nào roundtrong API C # làm được điều này (một phiên bản có một số chữ số thập phân để làm tròn thành, điều này không giống nhau).

Giả sử bạn chỉ phải xử lý các số nguyên của phần mười, nó đủ để tính toán round (num * 2) / 2. Nếu bạn đang sử dụng các số thập phân chính xác tùy ý, nó sẽ phức tạp hơn. Hãy hy vọng bạn không.


0

Tôi cũng gặp khó khăn với vấn đề này. Tôi chủ yếu viết mã trong Actionscript 3.0, đây là mã cơ bản cho Nền tảng Adobe Flash, nhưng có những điểm mô phỏng trong Ngôn ngữ:

Giải pháp tôi đã đưa ra như sau:

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

Nó khá là nhiều. Lưu ý việc sử dụng 'Số' và 'Số nguyên' và cách chúng được xử lý.

Chúc may mắn!


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
Mã này không giống C # như mong muốn trong câu hỏi. Nó làm gì? Vui lòng cung cấp một số giải thích thay vì chỉ là một đoạn mã bằng một ngôn ngữ không xác định.
AdrianHHH

-1

Cách chính xác để làm điều này là:

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

                return finalPrice;

            }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.