Округление от двойного до определенного числа десятичных знаков - Math.Round против Convert.ToDouble (ToString ()) - PullRequest
0 голосов
/ 08 сентября 2018

Предлагаемое решение проблемы округления (для отчетности):

private double RoundedResult(double v, int digits) 
{
    // return Math.Round(value, digits); 
    // sometimes does not do proper rounding per user feedback

    // proposed fix relies on a fixed decimal (F) format rendering converted back to double
    return
      Convert.ToDouble
      (
          v.ToString("F"+digits);
      );
}

Я не уверен относительно капризов формата F n .

Вопрос: Является ли вышеуказанное разумным решением?и может ли это вызвать другие проблемы позже?

Справочная информация

В отдельном отчете будет <1000 округленных чисел, поэтому я не беспокоюсь о производительности. </p>

Я работаю с устаревшей системой, использующей код приложения SQL Server и ASP NET MVC.Значения данных double?, а значения должны быть округлены до различного числа десятичных знаков для отчетности.Я знаю, что система должна использовать десятичные значения данных вместо double, но я застрял с унаследованным double.

Конечный пользователь жаловался на эту конкретную ситуацию (и другие подобные):

Файл текстовых данных имеет 0,000065, средство просмотра базы данных показывает 0,000065, а в отчете (до 5 десятичных знаков) отображается 0,00006 вместо 0,00007.Отчетность всегда должна округляться.

Информация о текстовом файле:

Я работаю с особенностями

double? value = 0.000065;

Я знаю, что 0.000065d должно быть немного меньше 0.000065m:

  • Math.Round(value.Value,5,...) возвращает 0.00006, используя MidpointRounding.AwayFromZero и ToEven.
  • Отладчик показывает 0.000065d-0.000065f as -1.7695129487117073E-13 double
  • Один бросок значения округляется, часы отладчика показывают
    • Math.Round((Single)value,5) 7E-05 double

Слегка озадачивает

  • value.Value.ToString("F5") возвращает "0.00007"

Я не знаю, выполняет ли F5 какое-либо внутреннее приведение, но результат соответствует округлению одиночного приведения,* В 1064 * (он же String.Format()) происходит какое-то mojo.

Одиночный случай округления одиночного броска двойного 0,000065 «сработало» с получением 0,0007, но, вероятно, не во всех случаях.

Код скрипты

Я написал .NET Fiddle , чтобы выполнить итерацию по большому количеству случаев, заканчивающихся в 5, и кажется,этот ToString («F5») всегда давал «ожидаемый человеком» результат.

...