2009-09-25 4 views
1

У меня есть метод C# и который принимает три параметра string. После преобразования их в decimal, я пытаюсь выполнить простой математический расчет. Я не понимаю, почему не правильный результат?Неверный математический расчет с десятичной точностью

decimal d = MyFunction(x, y, z); 


public decimal MyFunction(string x, string y, string z) 
{ 
    decimal dx = 0; 
    decimal dy = 0; 
    decimal dz = 0; 

    Decimal.TryParse(x, out dx); 
    Decimal.TryParse(y, out dy); 
    Decimal.TryParse(z, out dz); 

    decimal result = dx - dz + dy; 
    return result; 
} 

Заранее спасибо.

+15

Вам нужно указать более подробные сведения: какие значения x, y, z равны и что вы ожидаете получить в переменной результата? –

+1

Подумайте, о чем вы спрашиваете, и о том, что вы нам дали: «Почему« [unknownValue1] - [unknownValue2] + [unknownValue3] = [unknownValue4]] неправильно? –

+4

Если вы ожидали чего-то, кроме 151804.25, вы ошиблись. – erelender

ответ

6

Редактировать в ответе на дополнительные вопросы:
Я не вижу вашей проблемы. Я получаю 151804.25, что является правильным результатом (1186197.29 - 1260711.19) + 226318.15.

Возможно, вы сбиты с толку, потому что вы ожидаете, что x - z + y означает x - (z + y), а не (x - z) + y?
Прецедент оператора C# для - и + слева направо, поэтому он означает (x - z) + y. Если вы хотите, чтобы x - (z + y), вам придется написать его таким образом.


вычисления с плавающей запятой часто принципиально неточными (хотя decimal делает намного лучше, чем float и double денежной и аналогичного использования). Пример:

decimal x = 1m/3m; 
decimal y = 0; 

for (int i = 0; i < 1e6; i++) 
{ 
    y += x; 
} 

Результат y:

333333,33333333333333333072026

+4

@Joren: игнорируя проблемы с переполнением и допуская равную точность входов и выходов, добавление/вычитание с плавающей запятой * полностью точно. – Brian

+1

«Двоичное представление десятичного значения состоит из 1-битового знака, 96-битного целочисленного числа и коэффициента масштабирования, используемого для разделения 96-битного целого числа и определения того, какая его часть является десятичной дробью». Другими словами, это не приблизительное значение, например float или double. – Powerlord

+2

@R. Bemrose: множество действительных чисел бесконечно, а множество чисел, которое может быть представлено точно десятичным, конечно, поэтому десятичное значение все еще является приближением. – MusiGenesis

4

Если результат вы получаете ноль, то это может быть, что TryParse не мог разобрать строки ,

Вы должны заменить вызовы на TryParse на decimal dx = Decimal.Parse(x); и посмотреть, не вызывает ли это исключение.

Если это не проблема, мы не можем вам помочь, пока вы не предоставите более подробную информацию.

Что такое x, y и z равно, и какой результат вы получаете?

EDIT: В ответ на дополнительную информацию, добавленную к вопросу, кажется, что все остальные правильно и проблема, вероятно, отсутствие скобок.

+2

+1. Игнорирование результата при вызове TryParse означает, что есть три потенциальных момента отказа. Если строка не поддается анализу, значение будет равно нулю. – Guffa

+1

Это не проблема. Нет проблем. Ответ, возвращенный функцией Флорджона, правильный. –

+1

Ничего против вас, SLaks, но почему люди продолжают голосовать за этот ответ? Входы в вопросе обрабатываются штрафом. – MusiGenesis

2

Я думаю, что я вижу, в чем ваша проблема. Эта функция работает правильно, но внимательно посмотреть на этой линии:

decimal result = dx - dz + dy; 

Вы, возможно, намеревался написать это:

decimal result = dx + dz + dy; 

или это:

decimal result = dx - (dz + dy); 
+0

не работает даже таким образом. кажется, что значение правильное, но когда я делаю xxxx.29 - xxxx.19, он говорит, что равен xxxx.9 , это не имеет смысла. – Florjon

+0

@Florjon: как вы это понимаете? Когда я выполняю эту строку: «2000.29M - 1000.19M», я получаю «1000.1». – MusiGenesis

+2

Если первое число больше второго, ответ правильный: 1000.29 - 2000.19 = -999.9. –

2

Я сделал этот расчет (1186197.29 - 1260711.19 + 226318.15) три раза, и я получаю 151804.25.

M в конце номера просто означает, что это Decimal, кстати.

+0

Я сделал расчет с Mathematica с точным символическим расчетом и дал 607217/4 = (607217 * 25)/(4 * 25) = 15180425/100. Я думаю, мы можем быть уверены, что результат «десятичный» будет правильным. ;) – Joren

+0

Как видно из комментария плаката к ответу МусиГенезиса, он просто путается как-то об арифметике и пытается проверить ответ вручную. –

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