2010-03-25 6 views
6

Tôi đang cố gắng làm tròn số tới số thập phân đầu tiên và xem xét các tùy chọn MidpointRounding khác nhau, có vẻ như hoạt động tốt. Một vấn đề nảy sinh khi số đó có số thập phân tiếp theo sẽ ảnh hưởng không cân bằng đến làm tròn.Có cách nào để làm 'chính xác' làm tròn số học trong .NET không?/C#

Một ví dụ:

Với 0.1, 0.11..0.190.141..0.44 nó hoạt động:

Math.Round(0.1, 1) == 0.1 
Math.Round(0.11, 1) == 0.1 
Math.Round(0.14, 1) == 0.1 
Math.Round(0.15, 1) == 0.2 
Math.Round(0.141, 1) == 0.1 

Nhưng với 0.141..0.149 nó luôn luôn trả 0.1, mặc dù 0.146..0.149 tròn nên để 0.2:

Math.Round(0.145, 1, MidpointRounding.AwayFromZero) == 0.1 
Math.Round(0.146, 1, MidpointRounding.AwayFromZero) == 0.1 
Math.Round(0.146, 1, MidpointRounding.ToEven) == 0.1 
Math.Round(0.146M, 1, MidpointRounding.ToEven) == 0.1M 
Math.Round(0.146M, 1, MidpointRounding.AwayFromZero) == 0.1M 

tôi cố gắng tìm ra một dấu chấm câu ion giải quyết vấn đề này, và nó hoạt động tốt cho trường hợp này, nhưng tất nhiên nó không thành công nếu bạn cố gắng làm tròn tức là 0.144449 đến chữ số thập phân đầu tiên (phải là 0.2, nhưng kết quả là 0.1.) Math.round() một trong hai.)

private double "round"(double value, int digit) 
{ 
    // basically the old "add 0.5, then truncate to integer" trick 
    double fix = 0.5D/(Math.Pow(10D, digit+1))*(value >= 0 ? 1D : -1D); 
    double fixedValue = value + fix; 

    // 'truncate to integer' - shift left, round, shift right 
    return Math.Round(fixedValue * Math.Pow(10D, digit))/Math.Pow(10D, digit); 
} 

tôi giả sử một giải pháp sẽ được liệt kê tất cả chữ số, tìm giá trị đầu tiên lớn hơn 4 và sau đó vòng lên, nếu không làm tròn xuống. Vấn đề 1: Điều đó có vẻ ngu ngốc, Bài 2: Tôi không biết cách liệt kê các chữ số mà không có một gazillion phép nhân và phép trừ.

Câu chuyện dài: Cách tốt nhất để làm điều đó là gì?

+6

lý do tại sao nên 0.149 vòng đến 0,2 nó nhỏ hơn điểm giữa nên nó không được làm tròn lên. bạn có thực sự muốn cắt bớt và thêm 1 có thể không? –

Trả lời

20

Math.Round() hoạt động chính xác.

Khi bạn đang thực hiện làm tròn điểm giữa tiêu chuẩn, bạn không bao giờ cần phải nhìn xa hơn 1 chữ số thập phân ngoài nơi bạn làm tròn đến. Nếu bạn làm tròn đến phần mười gần nhất, thì bạn không bao giờ cần phải nhìn xa hơn chữ số thứ hai sau dấu thập phân.

Ý tưởng với làm tròn điểm giữa là một nửa số ở giữa phải tròn và một nửa sẽ tròn xuống. Vì vậy, đối với các số từ 0,1 đến 0,2, một nửa trong số đó phải tròn đến 0,1 và một nửa phải tròn 0,2. Điểm giữa giữa hai số này là 0,15, do đó, đó là ngưỡng để làm tròn lên. 0.146 nhỏ hơn 0.15, do đó nó phải làm tròn xuống 0.1.

    Midpoint 
0.10     0.15     0.20 
|----------------|----|---------------------| 
       0.146 
     <---- Rounds Down 
+0

Thực tế, đôi khi bạn cần phải nhìn xa hơn. Ví dụ, giả sử chúng ta đang sử dụng từ tròn đến mười phần trăm; 0,250 vòng đến 0,2 (chính xác là ở điểm giữa, vì vậy nó chuyển sang 0.2 thậm chí là số lẻ 0.3), nhưng 0.251 vòng thành 0.3 (vì nó gần với 0.3 hơn 0.2). Tôi nghĩ rằng chuỗi chữ số "50̅" (5 sau khi làm tròn vị trí của bạn theo sau bởi tất cả các số không) là trường hợp duy nhất bạn cần phải xem xét, mặc dù. –

+0

Bạn đã chính xác, tôi đã thực hiện một chỉnh sửa nhỏ. –

15

Tôi không nhận được những gì bạn đang cố gắng thực hiện ở đây. 0.149 được làm tròn đến một chữ số thập phân 0,1, không phải 0,2

+0

Vâng, hãy nghĩ rằng một số sửa đổi toán học cơ bản là cần thiết trước;) – Paolo

+0

Tôi hiểu (và hiểu) làm tròn như cắt ngắn đến một số chữ số với điều chỉnh chữ số cụ thể theo giá trị của, tốt, phần còn lại. Hoặc 0,15 là 0,15, là 0,2. Đừng phá hủy thế giới của tôi! – sunside

+3

Phải, bạn không bắt đầu làm tròn từ vị trí thập phân cuối cùng, sau đó làm việc. Bạn chỉ cần nhìn vào vị trí thập phân sau địa điểm bạn muốn làm tròn. –

5

Không thử và ghép các 'lỗi' làm tròn. Đó là những gì bạn đang cố gắng làm.

.146 nên làm tròn xuống đến .1 nếu bạn sắp tới một chữ số thập phân.

Bằng cách làm tròn nó thành .15 đầu tiên, sau đó lại thành .2 bạn chỉ giới thiệu nhiều lỗi làm tròn hơn, không ít hơn.

+0

Một sự hiểu lầm nghiêm trọng về phía tôi. Cảm ơn! – sunside

6

Làm tròn không phải là quá trình lặp lại, bạn chỉ làm tròn một lần.

Vì vậy, 0.146 được làm tròn thành 1 chữ số thập phân 0.1.

Bạn không làm điều này:

0.146 --> 0.15 
0.15 --> 0.2 

Bạn chỉ làm điều này:

0.146 --> 0.1 

Nếu không, sau đây:

0.14444444444444446 

cũng sẽ tròn đến 0,2, nhưng nó không, và không nên.