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); } }
public static decimal Normalize(decimal value) => DecimalRep.FromValue(value).Normalize().Value;