예제 #1
0
            public decimal Next(decimal value)
            {
                Debug.Assert(value != decimal.MaxValue);
                if (value == 0m)
                {
                    return(epsilon);
                }
                var(low, mid, high, isNegative, scale) = DecimalRep.FromValue(value);
                Debug.Assert(scale == DecimalRep.FromValue(value).Normalize().scale); // assert that the input is normalized
                if (isNegative)
                {
                    // get the next value closer to zero.(less negative)
                    if (value == -epsilon)
                    {
                        return(normalZero); // skip negative zero
                    }
                    // This should not occur, as numbers such as this are not in our normal form (not at maximum scale).
                    Debug.Assert(
                        !(
                            scale < 28 &&
                            low == transitionLow &&
                            mid == transitionMid &&
                            high == transitionHigh
                            )
                        );

                    if (low != 0)
                    {
                        return(new DecimalRep(
                                   low: low - 1,
                                   mid: mid,
                                   high: high,
                                   isNegative: isNegative,
                                   scale: scale
                                   ).Value);
                    }
                    if (mid != 0)
                    {
                        return(new DecimalRep(
                                   low: uint.MaxValue,
                                   mid: mid - 1,
                                   high: high,
                                   isNegative: isNegative,
                                   scale: scale
                                   ).Value);
                    }
                    Debug.Assert(high > 0); // otherwise value == 0m
                    return(new DecimalRep(
                               low: uint.MaxValue,
                               mid: uint.MaxValue,
                               high: high - 1,
                               isNegative: isNegative,
                               scale: scale
                               ).Value);
                }
                else
                {
                    // get the next value farther from zero.(more positive)
                    if (low != uint.MaxValue)
                    {
                        return(new DecimalRep(
                                   low: low + 1,
                                   mid: mid,
                                   high: high,
                                   isNegative: isNegative,
                                   scale: scale
                                   ).Value);
                    }
                    if (mid != uint.MaxValue)
                    {
                        return(new DecimalRep(
                                   low: 0,
                                   mid: mid + 1,
                                   high: high,
                                   isNegative: isNegative,
                                   scale: scale
                                   ).Value);
                    }
                    if (high != uint.MaxValue)
                    {
                        return(new DecimalRep(
                                   low: 0,
                                   mid: 0,
                                   high: high + 1,
                                   isNegative: isNegative,
                                   scale: scale
                                   ).Value);
                    }

                    // the mantissa it at its maximum value.  Divide the mantissa by 10 and decrease the scale.
                    // Since we know the value of the mantissa, we can simply assign mantissa/10 here.
                    low  = transitionLow;
                    mid  = transitionMid;
                    high = transitionHigh;
                    Debug.Assert(scale > 0); // otherwise value == decimal.MaxValue
                    scale -= 1;

                    var result =
                        new DecimalRep(
                            low: low + 1,
                            mid: mid,
                            high: high,
                            isNegative: isNegative,
                            scale: scale
                            ).Value;

                    // Assert that the value returned really is the next possible value.
                    Debug.Assert(
                        new DecimalRep(
                            low: low,
                            mid: mid,
                            high: high,
                            isNegative: isNegative,
                            scale: scale
                            ).Value <= value
                        );
                    Debug.Assert(result > value);
                    return(result);
                }
            }
예제 #2
0
 public static decimal Normalize(decimal value) =>
 DecimalRep.FromValue(value).Normalize().Value;