private void CalculateResultToPrice() { if (Amount > 0) { _price = DecimalRounding.RoundDown(Result / Amount, Pair.LeftCurrency.Decimals); OnPropertyChanged("Price"); } }
private void CalculateResultToAmount() { if (Price > 0) { _amount = DecimalRounding.RoundDown(Result / Price, Pair.RightCurrency.Decimals + 4); OnPropertyChanged("Amount"); } }
/// <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)); }
/// <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); }
private void CalculateResult() { _result = DecimalRounding.RoundDown(Price * Amount, Pair.RightCurrency.Decimals + 4); OnPropertyChanged("Result"); }
public void Round_MultipleOf(decimal exp, decimal value, decimal factor, DecimalRounding mode) { var act = value.RoundToMultiple(factor, mode); Assert.AreEqual(exp, act); }
public void Round_NearestAndDirect(decimal exp, decimal value, DecimalRounding mode) { var act = value.Round(0, mode); Assert.AreEqual(exp, act); }
/// <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;
/// <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;
/// <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)); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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);
/// <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);