Reputation: 10291
Given 2 values like so:
decimal a = 0.15m;
decimal b = 0.85m;
Where a + b
will always be 1.0m
, both values are only specified to 2 decimal places and both values are >= 0.0m
and <= 1.0m
Is it guaranteed that x == total
will always be true, for all possible Decimal values of x
, a
and b
? Using the calculation below:
decimal x = 105.99m;
decimal total = (x * a) + (x * b);
Or are there cases where x == total
only to 2 decimal places, but not beyond that?
Would it make any difference if a
and b
could be specified to unlimited decimal places (as much as Decimal
allows), but as long as a + b = 1.0m
still holds?
Upvotes: 5
Views: 3380
Reputation: 33139
The maximum precision of decimal
in the CLR is 29 significant digits. When you're using that kind of precision, you're really talking approximation especially if you do multiplication because that requires intermediate results that the CLR must be able to process (see also http://msdn.microsoft.com/en-us/library/364x0z75.aspx).
If you have x with 2 significant digits and, say, a with 20 significant digits, then x * a will already have a minimum precision of 22 digits, and possibly more may be needed for intermediate results.
If x always has only 2 significant digits and you can keep the number of significant digits in a and b low enough (say, 22 digits -- pretty good and probably far enough away from 27 to deal with rounding errors), then I suppose (x * a) + (x * b) should be a pretty precise calculation always.
Finally, whether a + b always makes up 1.0m is of no significance related to a and b's individual precisions.
Upvotes: 3
Reputation: 5132
Decimal is stored as a sign, an integer, and an integer exponent for the number 10 that represents the decimal location. So long as your integral portion of the number (e.g. 105 in 105.99) is not sufficiently large, then a + b will always equal one. and the outcome of your equation (x * a) + (x * b) will always have the correct value for the four decimal places.
Unlike float and double, precision is not lost up to the size of the data type (128 bits)
From MSDN:
The Decimal value type represents decimal numbers ranging from positive 79,228,162,514,264,337,593,543,950,335 to negative 79,228,162,514,264,337,593,543,950,335. The Decimal value type is appropriate for financial calculations requiring large numbers of significant integral and fractional digits and no round-off errors. The Decimal type does not eliminate the need for rounding. Rather, it minimizes errors due to rounding. For example, the following code produces a result of 0.9999999999999999999999999999 rather than 1
decimal dividend = Decimal.One;
decimal divisor = 3;
// The following displays 0.9999999999999999999999999999 to the console
Console.WriteLine(dividend/divisor * divisor);
Upvotes: 5