2009-09-14 2 views
9

Я не вижу результата, ожидаемого с помощью Math.Round.Округление до C#

return Math.Round(99.96535789, 2, MidpointRounding.ToEven); // returning 99.97 

Как я понимаю MidpointRounding.ToEven, 5 в положении тысячных должно вызывать выход быть 99,96. Разве это не так?

Я даже попытался это, но он вернулся 99,97, а также:

return Math.Round(99.96535789 * 100, MidpointRounding.ToEven)/100; 

Что я упускаю

Спасибо!

+4

Так что вы говорите, что вы хотите, чтобы это _round_ до числа, которое находится дальше? Это странное определение «округленное». –

+1

Это округление банкира для вас. Неудивительно, что мы в этом беспорядке ;-) –

+4

Нет, это не округление банкира. Банковское округление - это когда вы выбираете раунд до четного *, когда два варианта одинаково отдалены *. Вы не находитесь в ситуации, когда два варианта одинаково отдалены. Один из них ближе, чем другой, и вы хотите выбрать тот, который находится дальше. –

ответ

24

Вы на самом деле не находитесь в средней точке. MidpointRounding.ToEven указывает, что если у вас есть номер 99.965, т. Е. 99.96500000 [и т. Д.], , то вы получите 99.96. Поскольку число, которое вы переходите в Math.Round, находится выше этой середины, оно округляется.

Если вы хотите, чтобы ваш номер округлить до 99,96, сделать это:

// this will round 99.965 down to 99.96 
return Math.Round(Math.Truncate(99.96535789*1000)/1000, 2, MidpointRounding.ToEven); 

И эй, вот удобный маленькая функция сделать выше для общих случаев:

// This is meant to be cute; 
// I take no responsibility for floating-point errors. 
double TruncateThenRound(double value, int digits, MidpointRounding mode) { 
    double multiplier = Math.Pow(10.0, digits + 1); 
    double truncated = Math.Truncate(value * multiplier)/multiplier; 
    return Math.Round(truncated, digits, mode); 
} 
8

Это только раундов до 99,96, если вы находитесь в средней точке, то есть 99,965:

 
C:\temp>ipy 
IronPython 2.6 Beta 2 (2.6.0.20) on .NET 2.0.50727.4927 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import clr 
>>> from System import Math, MidpointRounding 
>>> Math.Round(99.9651, 2, MidpointRounding.ToEven) 
99.97 
>>> Math.Round(99.965, 2, MidpointRounding.ToEven) 
99.96 
>>> Math.Round(99.9649, 2, MidpointRounding.ToEven) 
99.96 
>>> Math.Round(99.975, 2, MidpointRounding.ToEven) 
99.98 
>>> 
+1

+1 для использования IronPython. Сделал меня улыбкой. –

+0

@ Винай, извините за мое редактирование Я был неправ. –

0

Среднее значение округления равно при условии, что значение находится между двумя вашими случаями.

В вашем случае это не «5», это «535 ...», поэтому оно больше, чем средняя точка, и работает с 0,96. Чтобы получить поведение, которое вы ожидаете, вам нужно будет соединиться с третьей точкой после запятой, затем с помощью MidpointRounding.ToEven.

4

Значение MidpointRounding только вступает в игру, когда вы пытаетесь округлить значение которого младший разряд именно 5. Другими словами, величина должна быть 99.965, чтобы получить желаемый результат. Так как это не так, вы просто наблюдаете стандартный механизм округления. См. MSDN page для получения дополнительной информации.

3

Вот результаты, которые проливают некоторый свет на эту тему:

Math.Round(99.96535789, 2, MidpointRounding.ToEven); // returning 99.97 
Math.Round(99.965, 2, MidpointRounding.ToEven);  // returning 99.96 
Math.Round(99.96500000, 2, MidpointRounding.ToEven); // returning 99.96 

Средняя точка находится ровно 5 ... не 535789, а не 499999.

0

раундов Math.Round»десятичного значения к указанное количество дробных цифр. ' при округлении 99,96500000,2 раундов до 99,96 и 99,96500001 до 99,67. Это округляет всю ценность.

0

Если бы это был я, я бы не использовал Math.Round(), потому что это не то, что вы пытаетесь выполнить.

Это то, что я хотел бы сделать:

double num = 99.96535789; 
double percentage = Math.Floor(100 * num)/100; 

Что гораздо легче читать и больше математического подхода.
Я умножаю число на 100, теперь у меня есть 9996.535789.
Затем наденьте его, отличное от округления, чтобы вернуть наименьшее целое число, самое близкое к числу, чтобы получить 9996.
Затем я разделяю 100, чтобы получить необходимый 99.96.

P.S.
Этаж является противоположностью потолка, который возвращает наибольшее целое число, самое близкое к числу.
Таким образом, потолок 9996.535789 составляет 9997.
Оба они отличаются от округлением до десятичных точек, что фактически возвращает самое близкое целое числу к числу, меньшее или большее - в зависимости от того, что ближе всего; поэтому вы получали 99.97, когда вы использовали округление.