Почему функции C# round и SQL round дают разные результаты?

Я использую ROUND функция от C# и SQL, и удивительно, что оба дают разные результаты.

в SQL: ROUND(1250.00, -2) = 1300

В C# ROUND 1250 С precision = 2 = 1200

кто-нибудь сталкивался с этой ситуацией раньше?

4 ответов


C# использует округление банкира по умолчанию, где, когда вы точно на .5 Марк, оно округляется до ближайшего четного числа, а не округления.

В разделе "примечания" в разделе статьи описывает это поведение. В основном это для уменьшения ошибок округления, когда вы накапливаете много округленных чисел вместе.


Если Вы читаете http://msdn.microsoft.com/en-us/library/wyk4d9cy.aspx, вы увидите, что округление по умолчанию "округляется до четного" (округление банкира), где в качестве SQL Server похоже, используется" стандартное " округление

обновление SQL Server либо делает симметричное арифметическое округление или симметричное округление (исправление) в зависимости от аргументов

Как решить проблему: реализовать пользовательскую процедуру округления: http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q196652&ID=KB;EN-US;Q196652


трудная часть в округлении что делать с 5 в десятичной. Они на самом деле ровно на полпути, так что они составляют ничью. Есть хороший бит о ничьи в завершение статьи Википедии. По сути, C# использует округление банкира, которое округляет вниз, когда последняя неокругленная цифра Четна, и вверх, когда она нечетна. Это соответствует стандарту IEEE. SQL вместо этого следует правилу "всегда Раунд 5's up".


используйте параметр в Math.Кругом,MidpointRounding, чтобы указать способ округления ваших чисел.

public enum MidpointRounding
{
    // When a number is halfway between two others, it is rounded toward
    // the nearest even number.
    ToEven = 0,

    // When a number is halfway between two others, it is rounded toward
    // the nearest number that is away from zero.
    AwayFromZero = 1,
}

вы можете использовать это так:

int presicion = 2;
double valueToRound;

Math.Round(valueToRound / Math.Pow(10, precision), MidpointRounding.AwayFromZero)
    * Math.Pow(10, precision);