Почему Math.Round (2.5) возвращает 2 вместо 3?

Я отвечу на ваш вопрос вместо того, чтобы быть сонным ноу-хау.

Да, вы можете одновременно указать на Wamperver и Tomcat на том же компьютере. По умолчанию Wamp привязывается к порту 80, который является портом по умолчанию для протокола http. Я считаю, что Tomcat привязывается к порту 8080, поэтому конфликт не должен быть, но если есть, просто измените Tomcat на 8080, и вы можете запускать их оба одновременно. Если вам нужно что-то маленькое и удобнее работать с Try Blazix.

Удачи вам.

379
задан Hans Passant 18 May 2016 в 06:03
поделиться

9 ответов

Во-первых, это все равно не будет ошибкой C # - это будет ошибка .NET. C # - это язык - он не решает, как реализован Math.Round .

И во-вторых, нет - если вы прочитаете документацию , вы увидите, что по умолчанию округление "округляется до четного" (банковское округление):

Возвращаемое значение
Тип: System.Double
Целое число, ближайшее к a. Если дробная составляющая а равна половине между двумя целыми числами, одно из которых четное и другое нечетное, затем четное номер возвращается. Обратите внимание, что это метод возвращает Double вместо интегральный тип.

Замечания
Поведение этого метода соответствует стандарту IEEE 754, раздел 4. Такое округление иногда называется округлением до ближайшего, или банковское округление. Сводит к минимуму ошибки округления, возникающие в результате последовательное округление среднего значения в одном направлении.

Вы можете указать, как Math.Round должен округлять средние точки, используя перегрузку , которая принимает значение MidpointRounding . Есть одна перегрузка с MidpointRounding , соответствующая каждой из перегрузок, у которой ее нет:

Другой вопрос, было ли это значение по умолчанию выбрано правильно или нет. ( MidpointRounding был введен только в .NET 2.0. До этого я ' Я не уверен, что существует какой-либо простой способ реализовать желаемое поведение, не выполняя его самостоятельно.) В частности, история показала, что это не ожидаемое поведение - и в большинстве случаев это кардинальный грех в разработке API. Я могу понять , почему Banker's Rounding полезно ... но это все еще сюрприз для многих.

Возможно, вам будет интересно взглянуть на ближайшее перечисление, эквивалентное Java ( RoundingMode ), который предлагает еще больше возможностей. (Это касается не только средних точек.)

Возможно, вам будет интересно взглянуть на ближайшее перечисление, эквивалентное Java ( RoundingMode ), которое предлагает еще больше возможностей. (Это касается не только средних точек.)

Возможно, вам будет интересно взглянуть на ближайшее перечисление, эквивалентное Java ( RoundingMode ), которое предлагает еще больше возможностей. (Это касается не только средних точек.)

537
ответ дан 22 November 2019 в 23:49
поделиться

Из MSDN, Math.Round (double a) возвращает:

Целое число, ближайшее к a. Если дробный компонент а находится посередине между двумя целыми числами, одно из которых является четным, а другое нечетным, то возвращается четное число.

... и так, 2.5, будучи на полпути между 2 и 3, округляется до четного числа (2). это называется Банковским округлением (или округлением до четного) и является широко используемым стандартом округления.

Та же статья MSDN:

Поведение этого метода соответствует стандарту IEEE 754, раздел 4. Этот вид округления иногда называют округлением до ближайшего или округлением банкира. Он сводит к минимуму ошибки округления, возникающие в результате последовательного округления значения средней точки в одном направлении.

Вы можете указать другое поведение округления, вызвав перегрузки Math.Round, которые принимают режим MidpointRounding.

42
ответ дан casperOne 18 May 2016 в 06:03
поделиться

В этом сообщении есть ответ, который вы ищете:

http://weblogs.asp.net/sfurman/archive/2003/03/07/3537.aspx

В основном вот что он говорит:

Возвращаемое значение

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

Поведение этого метода соответствует стандарту IEEE 754, раздел 4. Этот вид округления иногда называют округлением до ближайшего или банковским округлением. Если цифры равны нулю, такое округление иногда называют округлением в сторону нуля.

0
ответ дан 22 November 2019 в 23:49
поделиться

The nature of rounding

Consider the task of rounding a number that contains a fraction to, say, a whole number. The process of rounding in this circumstance is to determine which whole number best represents the number you are rounding.

In common, or 'arithmetic' rounding, it is clear that 2.1, 2.2, 2.3 and 2.4 round to 2.0; and 2.6, 2.7, 2.8 and 2.9 to 3.0.

That leaves 2.5, which is no nearer to 2.0 than it is to 3.0. It is up to you to choose between 2.0 and 3.0, either would be equally valid.

For minus numbers, -2.1, -2.2, -2.3 and -2.4, would become -2.0; and -2.6, 2.7, 2.8 and 2.9 would become -3.0 under arithmetic rounding.

For -2.5 a choice is needed between -2.0 and -3.0.

Other forms of rounding

'Rounding up' takes any number with decimal places and makes it the next 'whole' number. Thus not only do 2.5 and 2.6 round to 3.0, but so do 2.1 and 2.2.

Rounding up moves both positive and negative numbers away from zero. Eg. 2.5 to 3.0 and -2.5 to -3.0.

'Rounding down' truncates numbers by chopping off unwanted digits. This has the effect of moving numbers towards zero. Eg. 2.5 to 2.0 and -2.5 to -2.0

In "banker's rounding" - in its most common form - the .5 to be rounded is rounded either up or down so that the result of the rounding is always an even number. Thus 2.5 rounds to 2.0, 3.5 to 4.0, 4.5 to 4.0, 5.5 to 6.0, and so on.

'Alternate rounding' alternates the process for any .5 between rounding down and rounding up.

'Random rounding' rounds a .5 up or down on an entirely random basis.

Symmetry and asymmetry

A rounding function is said to be 'symmetric' if it either rounds all numbers away from zero or rounds all numbers towards zero.

A function is 'asymmetric' if rounds positive numbers towards zero and negative numbers away from zero.. Eg. 2.5 to 2.0; and -2.5 to -3.0.

Also asymmetric is a function that rounds positive numbers away from zero and negative numbers towards zero. Eg. 2.5 to 3.0; and -2.5 to -2.0.

Most of time people think of symmetric rounding, where -2.5 will be rounded towards -3.0 and 3.5 will be rounded towards 4.0. (in C# Round(AwayFromZero))

31
ответ дан 22 November 2019 в 23:49
поделиться

Это называется округлением до четности (или банковским округлением), которое является допустимой стратегией округления для минимизации накопленных ошибок в суммах (MidpointRounding.ToEven) . Теоретически, если вы всегда округляете число 0,5 в одном направлении, ошибки будут накапливаться быстрее (предполагается, что округление до четности минимизирует это) (a) .

Перейдите по этим ссылкам для описаний MSDN:

  • Math.Floor , который округляет до отрицательной бесконечности.
  • Math.Ceiling , который округляет до положительной бесконечности.
  • Math.Truncate , который округляет в большую или меньшую сторону до нуля.
  • Math.Round , который округляет до ближайшего целого числа или указанного количества десятичных знаков. Вы можете указать поведение, если оно точно равноудалено между двумя возможностями, например округление, чтобы последняя цифра была четной (" Round (2.5, MidpointRounding.ToEven) " становится 2) или так, чтобы она дальше от нуля (" Round (2.5, MidpointRounding.AwayFromZero) ) "становится 3).

Следующая диаграмма и таблица могут помочь:

-3        -2        -1         0         1         2         3
 +--|------+---------+----|----+--|------+----|----+-------|-+
    a                     b       c           d            e

                       a=-2.7  b=-0.5  c=0.3  d=1.5  e=2.8
                       ======  ======  =====  =====  =====
Floor                    -3      -1      0      1      2
Ceiling                  -2       0      1      2      3
Truncate                 -2       0      0      1      2
Round(ToEven)            -3       0      0      2      3
Round(AwayFromZero)      -3      -1      0      2      3

Обратите внимание, что Round намного эффективнее, чем кажется, просто потому, что он может округлять до определенного числа десятичных знаков. Все остальные числа всегда округляются до нуля. Например:

n = 3.145;
a = System.Math.Round (n, 2, MidpointRounding.ToEven);       // 3.14
b = System.Math.Round (n, 2, MidpointRounding.AwayFromZero); // 3.15

С другими функциями вы должны использовать уловку умножения / деления для достижения того же эффекта:

c = System.Math.Truncate (n * 100) / 100;                    // 3.14
d = System.Math.Ceiling (n * 100) / 100;                     // 3.15

(a) Конечно, эта теория зависит от того факта, что ваши данные имеют достаточно четный разброс значений между четными половинами (0,5, 2,5, 4,5, ...) и нечетными половинами (1,5, 3,5, ...).

Если все "половинные значения"

200
ответ дан 22 November 2019 в 23:49
поделиться

Из MSDN:

По умолчанию Math.Round использует MidpointRounding.ToEven. Большинство людей не знакомы с "округлением до даже "в качестве альтернативы" округление от нуля "чаще встречается учили в школе. .NET по умолчанию "Округление до четного" как есть статистически лучше, потому что не разделяет тенденции "округление от нуля" до округления в большую сторону немного чаще, чем округляется вниз (при условии, что числа с округлением обычно бывает положительным.)

http://msdn.microsoft.com/en-us/library/system.math.round.aspx

15
ответ дан 22 November 2019 в 23:49
поделиться

Вы должны проверить MSDN для Math.Round :

Поведение этого метода соответствует стандарту IEEE 754, раздел 4. Этот вид округления иногда называют округлением до ближайший, или округление банкира.

Вы можете указать поведение Math.Round с помощью перегрузки:

Math.Round(2.5, 0, MidpointRounding.AwayFromZero); // gives 3

Math.Round(2.5, 0, MidpointRounding.ToEven); // gives 2
37
ответ дан 22 November 2019 в 23:49
поделиться

Это чертовски уродливо, но всегда дает правильное арифметическое округление.

public double ArithRound(double number,int places){

  string numberFormat = "###.";

  numberFormat = numberFormat.PadRight(numberFormat.Length + places, '#');

  return double.Parse(number.ToString(numberFormat));

}
-2
ответ дан 22 November 2019 в 23:49
поделиться

The default MidpointRounding.ToEven, or Bankers' rounding (2.5 become 2, 4.5 becomes 4 and so on) has stung me before with writing reports for accounting, so I'll write a few words of what I found out, previously and from looking into it for this post.

Who are these bankers that are rounding down on even numbers (British bankers perhaps!)?

From wikipedia

The origin of the term bankers' rounding remains more obscure. If this rounding method was ever a standard in banking, the evidence has proved extremely difficult to find. To the contrary, section 2 of the European Commission report The Introduction of the Euro and the Rounding of Currency Amounts suggests that there had previously been no standard approach to rounding in banking; and it specifies that "half-way" amounts следует округлять в большую сторону.

Это кажется очень странным способом округления, особенно для банковского дела, если, конечно, банки не принимают много депозитов на равные суммы. Внесите 2,4 миллиона фунтов стерлингов, но мы назовем это 2 миллионами фунтов стерлингов.

Стандарт IEEE 754 восходит к 1985 году и дает оба способа округления, но с банковским, рекомендованным стандартом. В этой статье в Википедии есть длинный список того, как языки реализуют округление (поправьте меня, если что-то из приведенного ниже неверно), и большинство из них не используют округление банкиров, которое вас учат в школе:

  • C / C ++ round () из math.h округляет от нуля (не банковское округление)
  • Java Math.Round округляет от нуля (сводит результат к нулю, добавляет 0,5, приводит к целое число). Там' s альтернатива в BigDecimal
  • Perl использует способ, аналогичный C
  • Javascript такой же, как Java Math.Round.
25
ответ дан 22 November 2019 в 23:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: