/// <summary> /// Try parsing a correctly-formatted float floating-point literal into the nearest representable float /// using IEEE round-to-nearest-ties-to-even rounding mode. Behavior is not defined for inputs that are /// not valid C# floating-point literals. /// </summary> /// <param name="s">The float floating-point constant's string</param> /// <param name="f">The nearest float value, if conversion succeeds</param> /// <returns>True if the input was converted; false if there was an overflow</returns> public static bool TryParseFloat(string s, out float f) { DecimalFloatingPointString str = DecimalFloatingPointString.FromSource(s); FloatFloatingPointType dbl = FloatFloatingPointType.Instance; Status status = RealParser.ConvertDecimalToFloatingPointBits(str, dbl, out ulong result); f = Int32BitsToFloat((uint)result); return(status != Status.Overflow); }
/// <summary> /// Try parsing a correctly-formatted double floating-point literal into the nearest representable double /// using IEEE round-to-nearest-ties-to-even rounding mode. Behavior is not defined for inputs that are /// not valid C# floating-point literals. /// </summary> /// <param name="s">The decimal floating-point constant's string</param> /// <param name="d">The nearest double value, if conversion succeeds</param> /// <returns>True if the input was converted; false if there was an overflow</returns> public static bool TryParseDouble(string s, out double d) { DecimalFloatingPointString str = DecimalFloatingPointString.FromSource(s); DoubleFloatingPointType dbl = DoubleFloatingPointType.Instance; Status status = RealParser.ConvertDecimalToFloatingPointBits(str, dbl, out ulong result); d = BitConverter.Int64BitsToDouble((long)result); return(status != Status.Overflow); }
/// <summary> /// Try parsing a correctly-formatted float floating-point literal into the nearest representable float /// using IEEE round-to-nearest-ties-to-even rounding mode. Behavior is not defined for inputs that are /// not valid C# floating-point literals. /// </summary> /// <param name="s">The float floating-point constant's string</param> /// <param name="f">The nearest float value, if conversion succeeds</param> /// <returns>True if the input was converted; false if there was an overflow</returns> public static bool TryParseFloat(string s, out float f) { var str = DecimalFloatingPointString.FromSource(s); var dbl = FloatFloatingPointType.Instance; var status = ConvertDecimalToFloatingPointBits(str, dbl, out var result); f = Int32BitsToFloat((uint)result); return(status != Status.Overflow); }
/// <summary> /// Parse a sequence of digits into a BigInteger. /// </summary> /// <param name="data">The DecimalFloatingPointString containing the digits in its Mantissa</param> /// <param name="integer_first_index">The index of the first digit to convert</param> /// <param name="integer_last_index">The index just past the last digit to convert</param> /// <returns>The BigInteger result</returns> private static BigInteger AccumulateDecimalDigitsIntoBigInteger(DecimalFloatingPointString data, uint integer_first_index, uint integer_last_index) { if (integer_first_index == integer_last_index) { return(BigZero); } var valueString = data.Mantissa.Substring((int)integer_first_index, (int)(integer_last_index - integer_first_index)); return(BigInteger.Parse(valueString.TrimStart('0'))); // our bigint does octals too }
/// <summary> /// Try parsing a correctly-formatted float floating-point literal into the nearest representable float /// using IEEE round-to-nearest-ties-to-even rounding mode. Behavior is not defined for inputs that are /// not valid C# floating-point literals. /// </summary> /// <param name="s">The float floating-point constant's string</param> /// <param name="f">The nearest float value, if conversion succeeds</param> /// <returns>True of the input was converted; false if there was an overflow</returns> public static bool TryParseFloat(string s, out float f) { var str = DecimalFloatingPointString.FromSource(s); var dbl = FloatFloatingPointType.Instance; ulong result; var status = RealParser.ConvertDecimalToFloatingPointBits(str, dbl, out result); f = Int32BitsToFloat((uint)result); return(status != SLD_STATUS.SLD_OVERFLOW); }
/// <summary> /// Try parsing a correctly-formatted double floating-point literal into the nearest representable double /// using IEEE round-to-nearest-ties-to-even rounding mode. Behavior is not defined for inputs that are /// not valid C# floating-point literals. /// </summary> /// <param name="s">The decimal floating-point constant's string</param> /// <param name="d">The nearest double value, if conversion succeeds</param> /// <returns>True of the input was converted; false if there was an overflow</returns> public static bool TryParseDouble(string s, out double d) { var str = DecimalFloatingPointString.FromSource(s); var dbl = DoubleFloatingPointType.Instance; ulong result; var status = RealParser.ConvertDecimalToFloatingPointBits(str, dbl, out result); d = BitConverter.Int64BitsToDouble((long)result); return(status != SLD_STATUS.SLD_OVERFLOW); }
/// <summary> /// Parse a sequence of digits into a BigInteger. /// </summary> /// <param name="data">The DecimalFloatingPointString containing the digits in its Mantissa</param> /// <param name="integer_first_index">The index of the first digit to convert</param> /// <param name="integer_last_index">The index just past the last digit to convert</param> /// <returns>The BigInteger result</returns> private static BigInteger AccumulateDecimalDigitsIntoBigInteger(DecimalFloatingPointString data, uint integer_first_index, uint integer_last_index) { if (integer_first_index == integer_last_index) { return(s_bigZero); } var valueString = data.Mantissa.Substring((int)integer_first_index, (int)(integer_last_index - integer_first_index)); return(BigInteger.Parse(valueString)); }
/// <summary> /// Try parsing a correctly-formatted float floating-point literal into the nearest representable float /// using IEEE round-to-nearest-ties-to-even rounding mode. Behavior is not defined for inputs that are /// not valid C# floating-point literals. /// </summary> /// <param name="s">The float floating-point constant's string</param> /// <param name="f">The nearest float value, if conversion succeeds</param> /// <returns>True of the input was converted; false if there was an overflow</returns> public static bool TryParseFloat(string s, out float f) { try { var str = DecimalFloatingPointString.FromSource(s); var dbl = FloatFloatingPointType.Instance; ulong result; var status = RealParser.ConvertDecimalToFloatingPointBits(str, dbl, out result); f = Int32BitsToFloat((uint)result); return(status != Status.Overflow); } catch (System.FormatException) { f = 0.0f; return(false); } }
/// <summary> /// Try parsing a correctly-formatted double floating-point literal into the nearest representable double /// using IEEE round-to-nearest-ties-to-even rounding mode. Behavior is not defined for inputs that are /// not valid C# floating-point literals. /// </summary> /// <param name="s">The decimal floating-point constant's string</param> /// <param name="d">The nearest double value, if conversion succeeds</param> /// <returns>True of the input was converted; false if there was an overflow</returns> public static bool TryParseDouble(string s, out double d) { try { var str = DecimalFloatingPointString.FromSource(s); var dbl = DoubleFloatingPointType.Instance; ulong result; var status = RealParser.ConvertDecimalToFloatingPointBits(str, dbl, out result); d = BitConverter.Int64BitsToDouble((long)result); return(status != Status.Overflow); } catch (System.FormatException) { // this can occur when the exponent is empty (e.g. "0.0e") or too large to fit in an integer d = 0.0; return(false); } }
/// <summary> /// Convert a DecimalFloatingPointString to the bits of the given floating-point type. /// </summary> private static SLD_STATUS ConvertDecimalToFloatingPointBits(DecimalFloatingPointString data, FloatingPointType type, out ulong result) { if (data.Mantissa.Length == 0) { result = type.Zero; return(SLD_STATUS.SLD_NODIGITS); } // To generate an N bit mantissa we require N + 1 bits of precision. The // extra bit is used to correctly round the mantissa (if there are fewer bits // than this available, then that's totally okay; in that case we use what we // have and we don't need to round). uint requiredBitsOfPrecision = (uint)type.NormalMantissaBits + 1; // The input is of the form 0.Mantissa x 10^Exponent, where 'Mantissa' are // the decimal digits of the mantissa and 'Exponent' is the decimal exponent. // We decompose the mantissa into two parts: an integer part and a fractional // part. If the exponent is positive, then the integer part consists of the // first 'exponent' digits, or all present digits if there are fewer digits. // If the exponent is zero or negative, then the integer part is empty. In // either case, the remaining digits form the fractional part of the mantissa. uint positiveExponent = (uint)Math.Max(0, data.Exponent); uint integerDigitsPresent = Math.Min(positiveExponent, data.MantissaCount); uint integerDigitsMissing = positiveExponent - integerDigitsPresent; uint integerFirstIndex = 0; uint integerLastIndex = integerDigitsPresent; uint fractionalFirstIndex = integerLastIndex; uint fractionalLastIndex = data.MantissaCount; uint fractionalDigitsPresent = fractionalLastIndex - fractionalFirstIndex; // First, we accumulate the integer part of the mantissa into a big_integer: BigInteger integerValue = AccumulateDecimalDigitsIntoBigInteger(data, integerFirstIndex, integerLastIndex); if (integerDigitsMissing > 0) { if (integerDigitsMissing > type.OverflowDecimalExponent) { result = type.Infinity; return(SLD_STATUS.SLD_OVERFLOW); } MultiplyByPowerOfTen(ref integerValue, integerDigitsMissing); } // At this point, the integer_value contains the value of the integer part // of the mantissa. If either [1] this number has more than the required // number of bits of precision or [2] the mantissa has no fractional part, // then we can assemble the result immediately: byte[] integerValueAsBytes; uint integerBitsOfPrecision = CountSignificantBits(integerValue, out integerValueAsBytes); if (integerBitsOfPrecision >= requiredBitsOfPrecision || fractionalDigitsPresent == 0) { return(ConvertBigIntegerToFloatingPointBits( integerValueAsBytes, integerBitsOfPrecision, fractionalDigitsPresent != 0, type, out result)); } // Otherwise, we did not get enough bits of precision from the integer part, // and the mantissa has a fractional part. We parse the fractional part of // the mantsisa to obtain more bits of precision. To do this, we convert // the fractional part into an actual fraction N/M, where the numerator N is // computed from the digits of the fractional part, and the denominator M is // computed as the power of 10 such that N/M is equal to the value of the // fractional part of the mantissa. uint fractionalDenominatorExponent = data.Exponent < 0 ? fractionalDigitsPresent + (uint)-data.Exponent : fractionalDigitsPresent; if (integerBitsOfPrecision == 0 && (fractionalDenominatorExponent - (int)data.MantissaCount) > type.OverflowDecimalExponent) { // If there were any digits in the integer part, it is impossible to // underflow (because the exponent cannot possibly be small enough), // so if we underflow here it is a true underflow and we return zero. result = type.Zero; return(SLD_STATUS.SLD_UNDERFLOW); } BigInteger fractionalNumerator = AccumulateDecimalDigitsIntoBigInteger(data, fractionalFirstIndex, fractionalLastIndex); //Debug.Assert(!fractionalNumerator.IsZero); BigInteger fractionalDenominator = BigOne; MultiplyByPowerOfTen(ref fractionalDenominator, fractionalDenominatorExponent); // Because we are using only the fractional part of the mantissa here, the // numerator is guaranteed to be smaller than the denominator. We normalize // the fraction such that the most significant bit of the numerator is in // the same position as the most significant bit in the denominator. This // ensures that when we later shift the numerator N bits to the left, we // will produce N bits of precision. uint fractionalNumeratorBits = CountSignificantBits(fractionalNumerator); uint fractionalDenominatorBits = CountSignificantBits(fractionalDenominator); uint fractionalShift = fractionalDenominatorBits > fractionalNumeratorBits ? fractionalDenominatorBits - fractionalNumeratorBits : 0; if (fractionalShift > 0) { ShiftLeft(ref fractionalNumerator, fractionalShift); } uint requiredFractionalBitsOfPrecision = requiredBitsOfPrecision - integerBitsOfPrecision; uint remainingBitsOfPrecisionRequired = requiredFractionalBitsOfPrecision; if (integerBitsOfPrecision > 0) { // If the fractional part of the mantissa provides no bits of precision // and cannot affect rounding, we can just take whatever bits we got from // the integer part of the mantissa. This is the case for numbers like // 5.0000000000000000000001, where the significant digits of the fractional // part start so far to the right that they do not affect the floating // point representation. // // If the fractional shift is exactly equal to the number of bits of // precision that we require, then no fractional bits will be part of the // result, but the result may affect rounding. This is e.g. the case for // large, odd integers with a fractional part greater than or equal to .5. // Thus, we need to do the division to correctly round the result. if (fractionalShift > remainingBitsOfPrecisionRequired) { return(ConvertBigIntegerToFloatingPointBits( integerValueAsBytes, integerBitsOfPrecision, fractionalDigitsPresent != 0, type, out result)); } remainingBitsOfPrecisionRequired -= fractionalShift; } // If there was no integer part of the mantissa, we will need to compute the // exponent from the fractional part. The fractional exponent is the power // of two by which we must multiply the fractional part to move it into the // range [1.0, 2.0). This will either be the same as the shift we computed // earlier, or one greater than that shift: uint fractionalExponent = fractionalNumerator < fractionalDenominator ? fractionalShift + 1 : fractionalShift; ShiftLeft(ref fractionalNumerator, remainingBitsOfPrecisionRequired); BigInteger fractionalRemainder; BigInteger bigFractionalMantissa = BigInteger.DivideModulo(fractionalNumerator, fractionalDenominator, out fractionalRemainder); ulong fractionalMantissa = (ulong)bigFractionalMantissa; bool hasZeroTail = fractionalRemainder == BigZero; // We may have produced more bits of precision than were required. Check, // and remove any "extra" bits: uint fractionalMantissaBits = CountSignificantBits(fractionalMantissa); if (fractionalMantissaBits > requiredFractionalBitsOfPrecision) { int shift = (int)(fractionalMantissaBits - requiredFractionalBitsOfPrecision); hasZeroTail = hasZeroTail && (fractionalMantissa & ((1UL << shift) - 1)) == 0; fractionalMantissa >>= shift; } // Compose the mantissa from the integer and fractional parts: Debug.Assert(integerBitsOfPrecision < 60); // we can use BigInteger's built-in conversion ulong integerMantissa = (ulong)integerValue; ulong completeMantissa = (integerMantissa << (int)requiredFractionalBitsOfPrecision) + fractionalMantissa; // Compute the final exponent: // * If the mantissa had an integer part, then the exponent is one less than // the number of bits we obtained from the integer part. (It's one less // because we are converting to the form 1.11111, with one 1 to the left // of the decimal point.) // * If the mantissa had no integer part, then the exponent is the fractional // exponent that we computed. // Then, in both cases, we subtract an additional one from the exponent, to // account for the fact that we've generated an extra bit of precision, for // use in rounding. int finalExponent = integerBitsOfPrecision > 0 ? (int)integerBitsOfPrecision - 2 : -(int)(fractionalExponent) - 1; return(type.AssembleFloatingPointValue(completeMantissa, finalExponent, hasZeroTail, out result)); }
/// <summary> /// Parse a sequence of digits into a BigInteger. /// </summary> /// <param name="data">The DecimalFloatingPointString containing the digits in its Mantissa</param> /// <param name="integer_first_index">The index of the first digit to convert</param> /// <param name="integer_last_index">The index just past the last digit to convert</param> /// <returns>The BigInteger result</returns> private static BigInteger AccumulateDecimalDigitsIntoBigInteger(DecimalFloatingPointString data, uint integer_first_index, uint integer_last_index) { if (integer_first_index == integer_last_index) return BigZero; var valueString = data.Mantissa.Substring((int)integer_first_index, (int)(integer_last_index - integer_first_index)); return BigInteger.Parse(valueString); }
/// <summary> /// Convert a DecimalFloatingPointString to the bits of the given floating-point type. /// </summary> private static Status ConvertDecimalToFloatingPointBits(DecimalFloatingPointString data, FloatingPointType type, out ulong result) { if (data.Mantissa.Length == 0) { result = type.Zero; return Status.NoDigits; } // To generate an N bit mantissa we require N + 1 bits of precision. The // extra bit is used to correctly round the mantissa (if there are fewer bits // than this available, then that's totally okay; in that case we use what we // have and we don't need to round). uint requiredBitsOfPrecision = (uint)type.NormalMantissaBits + 1; // The input is of the form 0.Mantissa x 10^Exponent, where 'Mantissa' are // the decimal digits of the mantissa and 'Exponent' is the decimal exponent. // We decompose the mantissa into two parts: an integer part and a fractional // part. If the exponent is positive, then the integer part consists of the // first 'exponent' digits, or all present digits if there are fewer digits. // If the exponent is zero or negative, then the integer part is empty. In // either case, the remaining digits form the fractional part of the mantissa. uint positiveExponent = (uint)Math.Max(0, data.Exponent); uint integerDigitsPresent = Math.Min(positiveExponent, data.MantissaCount); uint integerDigitsMissing = positiveExponent - integerDigitsPresent; uint integerFirstIndex = 0; uint integerLastIndex = integerDigitsPresent; uint fractionalFirstIndex = integerLastIndex; uint fractionalLastIndex = data.MantissaCount; uint fractionalDigitsPresent = fractionalLastIndex - fractionalFirstIndex; // First, we accumulate the integer part of the mantissa into a big_integer: BigInteger integerValue = AccumulateDecimalDigitsIntoBigInteger(data, integerFirstIndex, integerLastIndex); if (integerDigitsMissing > 0) { if (integerDigitsMissing > type.OverflowDecimalExponent) { result = type.Infinity; return Status.Overflow; } MultiplyByPowerOfTen(ref integerValue, integerDigitsMissing); } // At this point, the integer_value contains the value of the integer part // of the mantissa. If either [1] this number has more than the required // number of bits of precision or [2] the mantissa has no fractional part, // then we can assemble the result immediately: byte[] integerValueAsBytes; uint integerBitsOfPrecision = CountSignificantBits(integerValue, out integerValueAsBytes); if (integerBitsOfPrecision >= requiredBitsOfPrecision || fractionalDigitsPresent == 0) { return ConvertBigIntegerToFloatingPointBits( integerValueAsBytes, integerBitsOfPrecision, fractionalDigitsPresent != 0, type, out result); } // Otherwise, we did not get enough bits of precision from the integer part, // and the mantissa has a fractional part. We parse the fractional part of // the mantsisa to obtain more bits of precision. To do this, we convert // the fractional part into an actual fraction N/M, where the numerator N is // computed from the digits of the fractional part, and the denominator M is // computed as the power of 10 such that N/M is equal to the value of the // fractional part of the mantissa. uint fractionalDenominatorExponent = data.Exponent < 0 ? fractionalDigitsPresent + (uint)-data.Exponent : fractionalDigitsPresent; if (integerBitsOfPrecision == 0 && (fractionalDenominatorExponent - (int)data.MantissaCount) > type.OverflowDecimalExponent) { // If there were any digits in the integer part, it is impossible to // underflow (because the exponent cannot possibly be small enough), // so if we underflow here it is a true underflow and we return zero. result = type.Zero; return Status.Undeflow; } BigInteger fractionalNumerator = AccumulateDecimalDigitsIntoBigInteger(data, fractionalFirstIndex, fractionalLastIndex); Debug.Assert(!fractionalNumerator.IsZero); BigInteger fractionalDenominator = BigOne; MultiplyByPowerOfTen(ref fractionalDenominator, fractionalDenominatorExponent); // Because we are using only the fractional part of the mantissa here, the // numerator is guaranteed to be smaller than the denominator. We normalize // the fraction such that the most significant bit of the numerator is in // the same position as the most significant bit in the denominator. This // ensures that when we later shift the numerator N bits to the left, we // will produce N bits of precision. uint fractionalNumeratorBits = CountSignificantBits(fractionalNumerator); uint fractionalDenominatorBits = CountSignificantBits(fractionalDenominator); uint fractionalShift = fractionalDenominatorBits > fractionalNumeratorBits ? fractionalDenominatorBits - fractionalNumeratorBits : 0; if (fractionalShift > 0) { ShiftLeft(ref fractionalNumerator, fractionalShift); } uint requiredFractionalBitsOfPrecision = requiredBitsOfPrecision - integerBitsOfPrecision; uint remainingBitsOfPrecisionRequired = requiredFractionalBitsOfPrecision; if (integerBitsOfPrecision > 0) { // If the fractional part of the mantissa provides no bits of precision // and cannot affect rounding, we can just take whatever bits we got from // the integer part of the mantissa. This is the case for numbers like // 5.0000000000000000000001, where the significant digits of the fractional // part start so far to the right that they do not affect the floating // point representation. // // If the fractional shift is exactly equal to the number of bits of // precision that we require, then no fractional bits will be part of the // result, but the result may affect rounding. This is e.g. the case for // large, odd integers with a fractional part greater than or equal to .5. // Thus, we need to do the division to correctly round the result. if (fractionalShift > remainingBitsOfPrecisionRequired) { return ConvertBigIntegerToFloatingPointBits( integerValueAsBytes, integerBitsOfPrecision, fractionalDigitsPresent != 0, type, out result); } remainingBitsOfPrecisionRequired -= fractionalShift; } // If there was no integer part of the mantissa, we will need to compute the // exponent from the fractional part. The fractional exponent is the power // of two by which we must multiply the fractional part to move it into the // range [1.0, 2.0). This will either be the same as the shift we computed // earlier, or one greater than that shift: uint fractionalExponent = fractionalNumerator < fractionalDenominator ? fractionalShift + 1 : fractionalShift; ShiftLeft(ref fractionalNumerator, remainingBitsOfPrecisionRequired); BigInteger fractionalRemainder; BigInteger bigFractionalMantissa = BigInteger.DivRem(fractionalNumerator, fractionalDenominator, out fractionalRemainder); ulong fractionalMantissa = (ulong)bigFractionalMantissa; bool hasZeroTail = fractionalRemainder.IsZero; // We may have produced more bits of precision than were required. Check, // and remove any "extra" bits: uint fractionalMantissaBits = CountSignificantBits(fractionalMantissa); if (fractionalMantissaBits > requiredFractionalBitsOfPrecision) { int shift = (int)(fractionalMantissaBits - requiredFractionalBitsOfPrecision); hasZeroTail = hasZeroTail && (fractionalMantissa & ((1UL << shift) - 1)) == 0; fractionalMantissa >>= shift; } // Compose the mantissa from the integer and fractional parts: Debug.Assert(integerBitsOfPrecision < 60); // we can use BigInteger's built-in conversion ulong integerMantissa = (ulong)integerValue; ulong completeMantissa = (integerMantissa << (int)requiredFractionalBitsOfPrecision) + fractionalMantissa; // Compute the final exponent: // * If the mantissa had an integer part, then the exponent is one less than // the number of bits we obtained from the integer part. (It's one less // because we are converting to the form 1.11111, with one 1 to the left // of the decimal point.) // * If the mantissa had no integer part, then the exponent is the fractional // exponent that we computed. // Then, in both cases, we subtract an additional one from the exponent, to // account for the fact that we've generated an extra bit of precision, for // use in rounding. int finalExponent = integerBitsOfPrecision > 0 ? (int)integerBitsOfPrecision - 2 : -(int)(fractionalExponent) - 1; return type.AssembleFloatingPointValue(completeMantissa, finalExponent, hasZeroTail, out result); }
/// <summary> /// Create a DecimalFloatingPointString from a string representing a floating-point literal. /// </summary> /// <param name="source">The text of the floating-point literal</param> public static DecimalFloatingPointString FromSource(string source) { StringBuilder mantissaBuilder = new StringBuilder(); int exponent = 0; int i = 0; while (i < source.Length && source[i] == '0') { i++; } int skippedDecimals = 0; while (i < source.Length && source[i] >= '0' && source[i] <= '9') { if (source[i] == '0') { skippedDecimals++; } else { mantissaBuilder.Append('0', skippedDecimals); skippedDecimals = 0; mantissaBuilder.Append(source[i]); } exponent++; i++; } if (i < source.Length && source[i] == '.') { i++; while (i < source.Length && source[i] >= '0' && source[i] <= '9') { if (source[i] == '0') { skippedDecimals++; } else { mantissaBuilder.Append('0', skippedDecimals); skippedDecimals = 0; mantissaBuilder.Append(source[i]); } i++; } } DecimalFloatingPointString result = default(DecimalFloatingPointString); result.Mantissa = mantissaBuilder.ToString(); if (i < source.Length && (source[i] == 'e' || source[i] == 'E')) { const int MAX_EXP = (1 << 30); // even playing ground char exponentSign = '\0'; i++; if (i < source.Length && (source[i] == '-' || source[i] == '+')) { exponentSign = source[i]; i++; } int firstExponent = i; int lastExponent = i; while (i < source.Length && source[i] >= '0' && source[i] <= '9') { lastExponent = ++i; } if (int.TryParse(source.Substring(firstExponent, lastExponent - firstExponent), out int exponentMagnitude) && exponentMagnitude <= MAX_EXP) { if (exponentSign == '-') { exponent -= exponentMagnitude; } else { exponent += exponentMagnitude; } } else { exponent = exponentSign == '-' ? -MAX_EXP : MAX_EXP; } } result.Exponent = exponent; return(result); }