C # против различий округления Python - PullRequest
0 голосов
/ 03 января 2019

Я разрабатываю приложение на python, некоторые части которого написаны на c # (для ускорения), и я озадачен, почему округление с плавающей запятой c # ведет себя как бы "противоположно" python при использовании функции round и строки с плавающей запятойФункции форматирования, вот пример:

Python (2.7)

>>> round(6.25, 1)
6.3
>>> "%.1f"%6.25
6.2

C #

>>> Math.Round(6.25,1)
6.2
>>> (6.25).ToString("F1")
6.3

Кто-нибудь понимает, почему поведение Python, по-видимому, "обращено" по сравнению сC #?Есть ли способ округлить «двойное» значение с плавающей запятой до N десятичных цифр, чтобы получить гарантированно одинаковый вывод строки между Python и C #?

Ответы [ 3 ]

0 голосов
/ 03 января 2019

Math.Round по умолчанию использует банковское округление, которое округляется до ближайшего четного значения (например, Math.Round(6.25,1) -> 6.2, как вы видели, и Math.Round(6.35,1) -> 6.4).Чтобы изменить это, используйте значение MidpointRounding, например Math.Round(6.25, 1, MidpointRounding.AwayFromZero).

Что касается другой проблемы, double.ToString () приводит к округлению.Обратитесь к C # Double - форматирование ToString () с двумя десятичными разрядами, но без округления для решения этой проблемы.

0 голосов
/ 03 января 2019

Это связано с разрешением средней точки двух методов, которые вы вызываете.

Python's round(number[, ndigits])

Возвращает округленное число с плавающей запятойдо ndigits цифр после десятичной точки.Если ndigits опущено, по умолчанию используется ноль.Результатом является число с плавающей запятой.Значения округляются до ближайшего кратного 10 к степени минус ndigits;если два множителя одинаково близки, округление выполняется вдали от 0 (например, round(0.5) равно 1.0 и round(-0.5) равно -1.0).

C # 's Math.Round(double, int)

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

Другими словами:

  • Python округляется от нуля (6.25 становится 6.3, потому что 6.3 дальше от 0, чем 6.2)
  • C #округляет до ближайшего четного числа, поэтому 6.25 становится 6.2, поскольку 6.2 является ближайшим четным числом.

Это можно исправить, используя одну из перегрузок на Math.Round, которая занимаетMidpointRounding значение enum , такое как Round (double, int, MidpointRounding) , например:

Math.Round(6.25, 1,  MidpointRounding.AwayFromZero);

, которое будет выполнять то же самое, что и округление Python.

0 голосов
/ 03 января 2019

Ссылаясь на Банковское округление .
Это целевая деталь реализации.Если вы хотите сохранить метод «всегда округлять 0,5» или любой другой способ округления, который вы желаете, вы можете сделать это, выполнив следующие действия:

import decimal
#The rounding you are looking for
decimal.Decimal('3.5').quantize(decimal.Decimal('1'), rounding=decimal.ROUND_HALF_UP)
>>> Decimal('4')
decimal.Decimal('2.5').quantize(decimal.Decimal('1'), rounding=decimal.ROUND_HALF_UP)
>>> Decimal('3')


#Other kinds of rounding
decimal.Decimal('2.5').quantize(decimal.Decimal('1'), rounding=decimal.ROUND_HALF_EVEN)
>>> Decimal('2')

decimal.Decimal('3.5').quantize(decimal.Decimal('1'), rounding=decimal.ROUND_HALF_DOWN)
>>> Decimal('3')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...