При указании количества десятичных знаков, корректно ли поведение Math.Round с MidpointRounding.ToEven?

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

Assert.AreEqual<double>(4d, Math.Round(4.5));          // Pass
Assert.AreEqual<double>(5d, Math.Round(4.6));          // Pass
Assert.AreEqual<double>(6d, Math.Round(5.5));          // Pass
Assert.AreEqual<double>(4d, Math.Round(4.500001));     // Fail - 5
Assert.AreEqual<double>(4d, Math.Round(4.45));         // Pass
Assert.AreEqual<double>(4.4, Math.Round(4.45, 1));     // Pass
Assert.AreEqual<double>(4.4, Math.Round(4.450001, 1)); // Fail - 4.5 

Поведение также то же самое для Decimal.Round.

Assert.AreEqual<decimal>(4m, Decimal.Round(4.500001m));      // Fail - 5
Assert.AreEqual<decimal>(4.4m, Decimal.Round(4.450001m, 2)); // Fail - 4.5

Не следует ли при округлении учитывать только цифру, следующую непосредственно за десятичным знаком, в который вы округляете, как описано в MidpointRounding?

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

1 ответ

Решение

Поведение правильное. Вы утверждаете, что 4.50001, 4.51, 4.59, 4.599999999999 должны округляться до 4. Очевидно, что цифры выше 4.5 ближе к 5, чем к 4, и поэтому должны быть округлены до 5.

Другие вопросы по тегам