Ejemplo n.º 1
0
 private void CalculateResultToPrice()
 {
     if (Amount > 0)
     {
         _price = DecimalRounding.RoundDown(Result / Amount, Pair.LeftCurrency.Decimals);
         OnPropertyChanged("Price");
     }
 }
Ejemplo n.º 2
0
 private void CalculateResultToAmount()
 {
     if (Price > 0)
     {
         _amount = DecimalRounding.RoundDown(Result / Price, Pair.RightCurrency.Decimals + 4);
         OnPropertyChanged("Amount");
     }
 }
Ejemplo n.º 3
0
 /// <summary>Rounds the percentage to a specified number of fractional
 /// digits. A parameter specifies how to round the value if it is midway
 /// between two numbers.
 /// </summary>
 /// <param name="decimals">
 /// The number of decimal places in the return value.
 /// </param>
 /// <param name="mode">
 /// Specification for how to round if it is midway between two other numbers.
 /// </param>
 /// <returns>
 /// The percentage nearest to the percentage that contains a number of
 /// fractional digits equal to <paramref name="decimals"/>. If the
 /// percentage has fewer fractional digits than <paramref name="decimals"/>,
 /// the percentage is returned unchanged.
 /// </returns>
 /// <exception cref="ArgumentOutOfRangeException">
 /// <paramref name="decimals"/> is less than 0 or greater than 26.
 /// </exception>
 /// <exception cref="ArgumentOutOfRangeException">
 /// <paramref name="mode"/> is not a valid value of <see cref="DecimalRounding"/>.
 /// </exception>
 public Percentage Round(int decimals, DecimalRounding mode)
 {
     if ((decimals < -26) || (decimals > 26))
     {
         throw new ArgumentOutOfRangeException(nameof(decimals), QowaivMessages.ArgumentOutOfRange_PercentageRound);
     }
     return(m_Value.Round(decimals + 2, mode));
 }
Ejemplo n.º 4
0
        /// <summary>Rounds a decimal value to a specified number of decimal places.</summary>
        /// <param name="value">
        /// A decimal number to round.
        /// </param>
        /// <param name="decimals">
        /// A value from -28 to 28 that specifies the number of decimal places to round to.
        /// </param>
        /// <param name="mode">
        /// The mode of rounding applied.
        /// </param>
        /// <returns>
        /// The decimal number equivalent to <paramref name="value"/> rounded to <paramref name="decimals"/> number of decimal places.
        /// </returns>
        /// <remarks>
        /// A negative value for <paramref name="decimals"/> lowers precision to tenfold, hundredfold, and bigger.
        /// </remarks>
        public static decimal Round(this decimal value, int decimals, DecimalRounding mode)
        {
            Guard.DefinedEnum(mode, nameof(mode));

            if ((decimals < -28) || (decimals > 28))
            {
                throw new ArgumentOutOfRangeException(nameof(decimals), QowaivMessages.ArgumentOutOfRange_DecimalRound);
            }

            var bits = decimal.GetBits(value);

            int scale           = (bits[3] & ScaleMask) >> 16;
            var scaleDifference = scale - decimals;

            if (scaleDifference <= 0)
            {
                return(value);
            }

            var b0       = (uint)bits[0];
            var b1       = (uint)bits[1];
            var b2       = (uint)bits[2];
            var negative = (bits[3] & SignMask) != 0;

            ulong remainder;
            uint  divisor;

            do
            {
                var diffCunck = (scaleDifference > MaxInt32Scale) ? MaxInt32Scale : scaleDifference;
                divisor          = Powers10[diffCunck];
                remainder        = InternalDivide(ref b0, ref b1, ref b2, divisor);
                scaleDifference -= diffCunck;
                scale           -= diffCunck;
            }while (scaleDifference > 0);

            if (ShouldRoundUp(b0, remainder, divisor, mode, !negative))
            {
                InternalAdd(ref b0, ref b1, ref b2, 1);
            }

            // For negative decimals, this can happen.
            while (scale < 0)
            {
                var diffChunk = (-scale > MaxInt32Scale) ? MaxInt32Scale : -scale;
                var factor    = Powers10[diffChunk];
                InternalMultiply(ref b0, ref b1, ref b2, factor);
                scale += diffChunk;
            }

            var lo = (int)b0;
            var mi = (int)b1;
            var hi = (int)b2;

            var rounded = new decimal(lo, mi, hi, negative, (byte)scale);

            return(rounded);
        }
Ejemplo n.º 5
0
 private void CalculateResult()
 {
     _result = DecimalRounding.RoundDown(Price * Amount, Pair.RightCurrency.Decimals + 4);
     OnPropertyChanged("Result");
 }
Ejemplo n.º 6
0
        public void Round_MultipleOf(decimal exp, decimal value, decimal factor, DecimalRounding mode)
        {
            var act = value.RoundToMultiple(factor, mode);

            Assert.AreEqual(exp, act);
        }
Ejemplo n.º 7
0
        public void Round_NearestAndDirect(decimal exp, decimal value, DecimalRounding mode)
        {
            var act = value.Round(0, mode);

            Assert.AreEqual(exp, act);
        }
Ejemplo n.º 8
0
 /// <summary>Rounds the money value to the closed number that is a multiple of the specified factor.</summary>
 /// <param name="multipleOf">
 /// The factor of which the number should be multiple of.
 /// </param>
 /// <param name="mode">
 /// The rounding method used to determine the closed by number.
 /// </param>
 public Money RoundToMultiple(decimal multipleOf, DecimalRounding mode) => m_Value.RoundToMultiple(multipleOf, mode) + Currency;
Ejemplo n.º 9
0
 /// <summary>Rounds the money value to a specified number of decimal places.</summary>
 /// <param name="decimals">
 /// A value from -28 to 28 that specifies the number of decimal places to round to.
 /// </param>
 /// <param name="mode">
 /// The mode of rounding applied.
 /// </param>
 /// <remarks>
 /// A negative value for <paramref name="decimals"/> lowers precision to tenfold, hundredfold, and bigger.
 /// </remarks>
 public Money Round(int decimals, DecimalRounding mode) => m_Value.Round(decimals, mode) + Currency;
Ejemplo n.º 10
0
 /// <summary>Rounds the percentage to a specified multiple of the specified percentage.</summary>
 /// <param name="multipleOf">
 /// The percentage of which the number should be multiple of.
 /// </param>
 /// <param name="mode">
 /// Specification for how to round if it is midway between two other numbers.
 /// </param>
 /// <exception cref="ArgumentOutOfRangeException">
 /// <paramref name="mode"/> is not a valid value of <see cref="DecimalRounding"/>.
 /// </exception>
 public Percentage RoundToMultiple(Percentage multipleOf, DecimalRounding mode)
 {
     return(m_Value.RoundToMultiple((decimal)multipleOf, mode));
 }
Ejemplo n.º 11
0
 /// <summary>Rounds a value to the closed number that is a multiple of the specified factor.</summary>
 /// <param name="value">
 /// The value to round to.
 /// </param>
 /// <param name="multipleOf">
 /// The factor of which the number should be multiple of.
 /// </param>
 /// <param name="mode">
 /// The rounding method used to determine the closed by number.
 /// </param>
 /// <returns>
 /// A rounded number that is multiple to the specified factor.
 /// </returns>
 public static decimal RoundToMultiple(this decimal value, decimal multipleOf, DecimalRounding mode)
 {
     Guard.Positive(multipleOf, nameof(multipleOf));
     return((value / multipleOf).Round(0, mode) * multipleOf);
 }
Ejemplo n.º 12
0
 /// <summary>Returns true if rounding is to the nearest. These modes have half-way tie-breaking rule.</summary>
 public static bool IsNearestRouding(this DecimalRounding mode)
 {
     return(mode >= DecimalRounding.ToEven && mode <= DecimalRounding.RandomTieBreaking);
 }
Ejemplo n.º 13
0
        /// <summary>Returns true if the rounding should be up, otherwise false.</summary>
        private static bool ShouldRoundUp(ulong b0, ulong remainder, ulong divisor, DecimalRounding mode, bool isPositive)
        {
            if (remainder == 0 || mode == DecimalRounding.Truncate)
            {
                return(false);
            }

            if (mode.IsDirectRounding())
            {
                switch (mode)
                {
                case DecimalRounding.DirectAwayFromZero:
                    return(true);

                case DecimalRounding.DirectTowardsZero:
                    return(false);

                case DecimalRounding.Ceiling:
                    return(isPositive);

                case DecimalRounding.Floor:
                    return(!isPositive);
                }
            }

            var halfway = divisor >> 1;

            if (remainder == halfway && mode.IsNearestRouding())
            {
                switch (mode)
                {
                case DecimalRounding.ToEven:
                    return((b0 & 1) == 1);

                case DecimalRounding.ToOdd:
                    return((b0 & 1) == 0);

                case DecimalRounding.AwayFromZero:
                    return(true);

                case DecimalRounding.TowardsZero:
                    return(false);

                case DecimalRounding.Up:
                    return(isPositive);

                case DecimalRounding.Down:
                    return(!isPositive);

                // Pick a 50-50 random.
                case DecimalRounding.RandomTieBreaking:
                    return((Random().Next() & 1) == 0);
                }
            }

            if (mode == DecimalRounding.StochasticRounding)
            {
                var ratio = remainder / (double)divisor;
                return(Random().NextDouble() <= ratio);
            }

            return(remainder >= halfway);
        }
Ejemplo n.º 14
0
 /// <summary>Returns true if the rounding is direct; the nearest of the two options is not relevent.</summary>
 public static bool IsDirectRounding(this DecimalRounding mode)
 {
     return(mode >= DecimalRounding.Truncate && mode <= DecimalRounding.Floor);
 }
Ejemplo n.º 15
0
 /// <summary>Rounds the amount value to the closed number that is a multiple of the specified factor.</summary>
 /// <param name="multipleOf">
 /// The factor of which the number should be multiple of.
 /// </param>
 /// <param name="mode">
 /// The rounding method used to determine the closed by number.
 /// </param>
 public Amount RoundToMultiple(decimal multipleOf, DecimalRounding mode) => (Amount)m_Value.RoundToMultiple(multipleOf, mode);
Ejemplo n.º 16
0
 /// <summary>Rounds the amount value to a specified number of decimal places.</summary>
 /// <param name="decimals">
 /// A value from -28 to 28 that specifies the number of decimal places to round to.
 /// </param>
 /// <param name="mode">
 /// The mode of rounding applied.
 /// </param>
 /// <remarks>
 /// A negative value for <paramref name="decimals"/> lowers precision to tenfold, hundredfold, and bigger.
 /// </remarks>
 public Amount Round(int decimals, DecimalRounding mode) => (Amount)m_Value.Round(decimals, mode);