views:

1038

answers:

4

I have a C# method and which accepts three string parameters. After converting them to decimal, I am trying to perform a simple math calculation. I don't understand, why isn't the result correct?

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;
 }

Thanks in advance.

+5  A: 

Edit in response to more question information:
I don't see your problem. I get 151804.25, which is the correct result of doing (1186197.29 - 1260711.19) + 226318.15.

Maybe you're confused because you expect x - z + y to mean x - (z + y) and not (x - z) + y?
C# operator precedence for - and + is left to right, so it means (x - z) + y. If you want x - (z + y), you will have to write it that way.


Floating point calculations are often fundamentally inexact (although decimal does a lot better than float and double for monetary and similar usage). Example:

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

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

Result of y:

333333.33333333333333333072026

Joren
@Joren: Ignoring overflow issues, and assuming equal precision of inputs and outputs, floating decimal point addition/subtraction *are* completely exact.
Brian
"The binary representation of a Decimal value consists of a 1-bit sign, a 96-bit integer number, and a scaling factor used to divide the 96-bit integer and specify what portion of it is a decimal fraction." In other words, it's not an approximated value like float or double.
R. Bemrose
@R. Bemrose: the set of real numbers is infinite, while the set of numbers that can be represented exactly by a Decimal is finite, so a Decimal is still an approximation.
MusiGenesis
Edited my answer to show an example of `decimal` being inexact. I wouldn't call this overflow, this is simply a consequence of limited precision. Limited precision is pretty fundamental to this kind of datatype.
Joren
Although it was wrong for me to say they're *never* exact. That's blatantly untrue. Edited that as well.
Joren
+4  A: 
SLaks
+1. Ignoring the result from the TryParse calls means that there are three potential points of failure. If a string is unparsable, the value will be zero.
Guffa
This is not the problem. There is no problem. The answer returned by Florjon's function is correct.
Dan Tao
Nothing against you, SLaks, but why do people keep voting this answer up? The inputs in the question parse fine.
MusiGenesis
Because I answered before he added the inputs to the question.
SLaks
+3  A: 

I think I see what your problem is. This function is working correctly, but look closely at this line:

decimal result = dx - dz + dy;

You may have intended to write this:

decimal result = dx + dz + dy;

or this:

decimal result = dx - (dz + dy);
MusiGenesis
don't work even in this way. it seems that the value are right, but when i am doing xxxx.29 - xxxx.19 it says that is equal to xxxx.9this doesn't make sense.
Florjon
@Florjon: how are you getting that? When I execute this line: "2000.29M - 1000.19M", I get "1000.1".
MusiGenesis
If the first number is greater than the second, the answer is correct: 1000.29 - 2000.19 = -999.9.
Ralph Rickenbach
@Ralph: I think you meant, "If the *second* number is greater than the *first* ...and they **ARE** in this case: 1260711.19 > 1186197.29.
Dan Tao
@Dan: True, thanks. I did turn that around. My math in this case is clearer then my English. As any mathematician would tell you: just trust the formulas.
Ralph Rickenbach
@Ralph: I think you hit the nail right between the eyes. The question asker needs a math class.
MusiGenesis
@Ralph: Indeed, in this case it seems the poster's biggest mistake was simply not trusting the computer.
Dan Tao
@MusiGenesis: Hit the *nail* right between the *eyes*? That's some nail ;)
Dan Tao
Brilliant. I'm remembering that expression. :)
Joren
I use that expression so much that sometimes I use it even when I *mean* to say "hit the nail right on the head". Oh well, it's half of one, six dozen of the other.
MusiGenesis
+2  A: 

I have done this calculation (1186197.29 - 1260711.19 + 226318.15) three times over now, and I am getting 151804.25.

The M at the end of the number just means it's a Decimal, by the way.

Dan Tao
I did the calculation with Mathematica, with exact symbolic calculation, and it gives 607217/4 = (607217 * 25)/(4 * 25) = 15180425/100. I think we can be pretty sure the `decimal` result is correct. ;)
Joren
It seems from the poster's comment on MusiGenesis's answer that he/she is merely confused somehow about the arithmetic itself and is trying to check the answer manually.
Dan Tao