2016-07-01 4 views
0

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

У меня есть этот расчет:

decimal tempDecimal = 15M/78M; 
decimal resultDecimal = tempDecimal * 13M; 

Здесь resultDecimal является +2,4999999999999999, когда правильный ответ на 13 * 15/78 составляет 2,5. Кажется, это потому, что tempDecimal (результат 15/78) является повторяющимся десятичным значением.

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

Если я использую два раза вместо:

double tempDouble = 15D/78D; 
double resultDouble = tempDouble * 13D; 

Затем я получаю 2.5 в resultDouble, который является ответом, который я ищу.

Из этого примера я чувствую, что лучше использовать удвоения или поплавки, даже если они имеют меньшую точность. Я предполагаю, что мне удается получить неправильный результат 2.4999999999999999 просто потому, что десятичная точка может хранить результат до такого количества знаков после запятой, тогда как двойной округляет его.

Должен ли я использовать двойники вместо этого?

EDIT: этот расчет используется в финансовом программном обеспечении для определения того, сколько контрактов распределено для разных портфелей, поэтому важно выбирать между 2 или 3. Меня больше интересует правильный расчет, чем со скоростью.

+6

Вероятно, вы можете найти другую ситуацию, когда результат десятичной точности правильный, а двойной результат - неправильный. –

+1

Если вы делаете научные или инженерные расчеты, а не финансовые расчеты, вы все равно должны использовать 'double', так как это в сотни раз быстрее, чем' decimal'. –

+0

@Damien_The_Unbeliever Я мог видеть, что я не могу получить результат для большого количества десятичных знаков с двойным, но учитывая, что я в конечном счете округляю до нуля десятичных разрядов, мне очень нравится получить неправильный конечный результат с двойным? –

ответ

1

Странная вещь, если вы пишете все это на одной строке, она будет равна 2.5.

Если точность является критической (финансовые расчеты), вы должны определенно использовать десятичную. Вы можете напечатать округленное десятичное число, используя Math.Round(myDecimalValue, signesAfterDecimalPoint) или String.Format("{0:0.00}", myDecimalValue), но сделайте расчеты с точным номером. В противном случае двойной будет просто отлично.

+0

Если я попробую 15M/78M * 13M, он все равно дает мне 2.4999999999999999. Я знаю, что 13M * 15M/78M дает правильный ответ, но это потому, что умножение происходит первым. Я бы предпочел не делать умножение сначала в моем примере, потому что существует вероятность переполнения числа. –

+1

@DavidJohnston: совет здесь лучший, который может дать любой. Компьютеры не волшебны; любой числовой тип будет иметь конкретные ограничения на числа, которые тип может представлять. Просто потому, что вы столкнулись с отношением, которое 'decimal' не может точно представлять, не означает, что' decimal' является неправильным типом для вашего сценария. Вы говорите, что имеете дело с финансовыми расчетами, поэтому «десятичный» определенно является правильным выбором здесь. Но вы все еще должны осознавать возможность неточности. Даже «decimal' не может точно представлять« 1/3 ». –

+1

@DavidJohnston: Вам решать форматировать номера, когда они отображаются пользователям, чтобы определить разницу между тем, как люди имеют дело с цифрами и как с ними справляются компьютеры.Пусть компьютер имеет дело с номером на своем пути и использует соответствующие коды форматирования для округления номера компьютера до чего-то полезного для человека, когда вы показываете это число человеку. –

Смежные вопросы