C # How to divide decimal places without implicit rounding

In C #, when you do the division of two decimal places, the last digit of the result will be automatically rounded if the true mathematical result cannot be accurately stored as a decimal type.

I want to write a function that performs division, where the last digit is always rounded, even if the figure to the right of the last usually causes rounding.

My function will be declared as MyDivide (decimal a, decimal b)

As an example, MyDivide (2.0M, 3.0M) => 0.666666666666666666666666666666

whereas the C # division operator would give 2.0M / 3.0M => 0.666666666666666666666666666667

Any help in implementing this is appreciated.

+6
decimal c # division
source share
2 answers

You will need to do the long division yourself. There is no way to finalize the built-in separation for this for you (hint: you cannot distinguish between 2m / 3m and .6666666666666666666666666667m / 1m or 6666666666666666666666666667m / 10000000000000000000000000000m , for that matter).

+3
source share

There is no easy way to make it split what you want, but you can detect rounding and fix it. Since the decimal mantissa is 96 bits, you cannot hold it in long or double , so I use the .Net 4 BigInteger object. I simply multiply the mantissa of the denominator and the quotient and compare it with the numerator (adjusted for the multiplication result metric). If the result is larger than the numerator, then the division should be rounded from zero, so I just need to subtract 1 in the least significant position from the quotient. To do this, I create a decimal number with 1 for the mantissa and a factor exponent for its exponent.

 using System; using System.Numerics; using System.Collections.Generic; namespace DivTest { class Divide { public static decimal MyDivide(decimal numerator, decimal denominator) { var quotient = numerator / denominator; // turn decimals into mantissas (BigInts) and exponents int nExp, dExp, qExp; var nMan = MantissaOfDecimal(num, out nExp); var dMan = MantissaOfDecimal(denom, out dExp); var qMan = MantissaOfDecimal(quotient, out qExp); // multiply quotient times denominator and compare with numerator if (dMan * qMan > nMan * BigInteger.Pow(10, dExp + qExp - nExp)) { // quotient was rounded away from zero, so subtract LSB // to round back toward zero quotient -= new decimal(1, 0, 0, quotient < 0, (byte)qExp); } return quotient; } static BigInteger MantissaOfDecimal(decimal d, out int exponent) { var ints = decimal.GetBits(d); exponent = (ints[3] >> 16) & 0xFF; var bytes = new List<byte>(13); // create a BigInteger containing the mantissa of the decimal value bytes.AddRange(BitConverter.GetBytes(ints[0])); bytes.AddRange(BitConverter.GetBytes(ints[1])); bytes.AddRange(BitConverter.GetBytes(ints[2])); bytes.Add(0); // avoid high bits being interpreted as negative return new BigInteger(bytes.ToArray()); } static void Main() { decimal num = 2m, denom = 3m; Console.WriteLine("Divide: " + num / denom); Console.WriteLine("MyDivide: " + MyDivide(num, denom)); } } } 

The output of the specified program:

  Divide: 0.666666666666666666666666666667
 MyDivide: 0.666666666666666666666666666666
+2
source share

All Articles